9.2 循环变化

9.2.1 修改已有对象

res <- 1:100
for(i in seq_along(res)){
  res[i] <- res[i] * i
}
str(res)
#>  int [1:100] 1 4 9 16 25 36 49 64 81 100 ...

9.2.2 循环模式

共有三种遍历向量的方法,之前展示的都是遍历数字索引for (i in seq_along(xs)),并使用提取值x[[i]]。除此之外,还有两种方式:

  • 循环遍历元素

for(i in xs),例如我们需要保存文件时,可以利用这种循环模式

  • 遍历名称

for (nm in names(xs)),我们可以使用x[[nm]] 该名称访问.当我们要在文件名中使用名称时会比较方便.

results <- vector("list", length(x))
names(results) <- names(x)

数字索引的循环模式最常用,因为可以根据位置提取名称和值.

for (i in seq_along(x)) {
  name <- names(x)[[i]]
  value <- x[[i]]
}

9.2.3 未知长度输出

有时候我们的循环我们不确定输出的长度是多少.这样会逐步增加向量的长度,如下所示:

means <- c(0, 1, 2)

output <- double()
for (i in seq_along(means)) {
  n <- sample(100, 1)
  output <- c(output, rnorm(n, means[[i]]))
}
str(output)
#>  num [1:69] 0.255 -0.553 1.405 -0.795 -1.567 ...

但是这种方式浪费时间,当数据量大时候效率会很低下。因为时间复杂度为(\(O(n^2)\)),解决方案是将结果保存在列表中,然后在完成循环后合并为单个向量:

out <- vector("list", length(means))
for (i in seq_along(means)) {
  n <- sample(100, 1)
  out[[i]] <- rnorm(n, means[[i]])
}
str(out)
#> List of 3
#>  $ : num [1:89] -1.399 0.259 -0.442 0.569 2.127 ...
#>  $ : num [1:81] 2.36 0.929 0.728 -1.447 1.065 ...
#>  $ : num [1:35] 0.0381 2.946 2.549 1.4225 0.7717 ...
str(unlist(out)) #unlist将列表向量化
#>  num [1:205] -1.399 0.259 -0.442 0.569 2.127 ...