我们都知道,向 R 中的for循环中的向量追加向量是一件坏事,因为它需要花费时间。解决方案是以矢量化样式执行此操作。 Here是约书亚乌尔里希的一个很好的例子。重要的是首先创建一个已知长度的矢量,然后将其填满,而不是将每个新片段附加到循环中的现有片段。
尽管如此,在他的例子中,他还展示了“仅”如何一次附加一个数据片段。我现在正在努力用矢量填充矢量 - 而不是标量。
想象一下,我有一个长度为100的矢量
vector <- numeric(length=100)
和一个较小的矢量,可以在第一个矢量中适合10次
vec <- seq(1,10,1)
我如何构建一个循环,将较小的向量添加到大型向量而不使用c()或追加?
编辑:这个例子是简化的 - vec并不总是由相同的序列组成,而是在for循环中生成,应该添加到vector中。
答案 0 :(得分:3)
您可以在循环中使用法向量索引来完成此任务:
vector <- numeric(length=100)
for (i in 1:10) {
vector[(10*i-9):(10*i)] <- 1:10
}
all.equal(vector, rep(1:10, 10))
# [1] TRUE
当然,如果您只是尝试重复一次向量,则rep(vec, 10)
将成为首选解决方案。
答案 1 :(得分:2)
类似的方法,如果您的新向量具有可变长度,可能会更清楚一点:
# Let's over-allocate so that we now the big vector is big enough
big_vec = numeric(1e4)
this.index = 1
for (i in 1:10) {
# Generate a new vector of random length
new_vec = runif(sample(1:20, size = 1))
# Stick in in big_vec by index
big_vec[this.index:(this.index + length(new_vec) - 1)] = new_vec
# update the starting index
this.index = this.index + length(new_vec)
}
# truncate to only include the added values
big_vec = big_vec[1:(this.index - 1)]
正如@josilber在评论中所建议的,列表会更多R-ish。这是一种更清晰的方法,除非新的向量生成依赖于先前的向量,在这种情况下,for循环可能是必要的。
vec_list = list()
for (i in 1:10) {
# Generate a new vector of random length
vec_list[[i]] = runif(sample(1:20, size = 1))
}
# Or, use lapply
vec_list = lapply(1:10, FUN = function(x) {runif(sample(1:20, size = 1))})
# Then combine with do.call
do.call(c, vec_list)
# or more simply, just unlist
unlist(vec_list)