在R中向空向量附加值?

我试图学习R,我不知道如何追加到列表。

如果这是Python我会的。 。 。

#Python vector = [] values = ['a','b','c','d','e','f','g'] for i in range(0,len(values)): vector.append(values[i]) 

你如何在R中做到这一点?

 #R Programming > vector = c() > values = c('a','b','c','d','e','f','g') > for (i in 1:length(values)) + #append value[i] to empty vector 

这里有几种方法来做到这一点。 他们都不鼓励。 在for循环中追加一个对象会导致整个对象在每次迭代时被复制,这导致很多人说“R很慢”,或者“应该避免R循环”。

 # one way for (i in 1:length(values)) vector[i] <- values[i] # another way for (i in 1:length(values)) vector <- c(vector, values[i]) # yet another way?!? for (v in values) vector <- c(vector, v) # ... more ways 

help("append")会回答你的问题,并节省了你写这个问题的时间(但会导致你养成坏习惯)。 😉

请注意, vector <- c()不是一个空向量。 它是NULL 。 如果你想要一个空的字符vector,使用vector <- character()

另外请注意,正如BrodieG在评论中指出的:如果你绝对必须使用for循环,那么至less在循环之前预先分配整个向量。 这将比追加更大的向量要快得多。

 set.seed(21) values <- sample(letters, 1e4, TRUE) vector <- character(0) # slow system.time( for (i in 1:length(values)) vector[i] <- values[i] ) # user system elapsed # 0.340 0.000 0.343 vector <- character(length(values)) # fast(er) system.time( for (i in 1:length(values)) vector[i] <- values[i] ) # user system elapsed # 0.024 0.000 0.023 

FWIW:类似于python的append():

 b <- 1 b <- c(b, 2) 

你有几个select:

 c(vector, values) append(vector, values) vector[(length(vector) + 1):(length(vector) + length(values))] <- values 

第一个是标准方法。 第二个给你select追加除了最后的地方。 最后一个是有点扭曲,但有修改vector的优点(虽然真的,你可以很容易做vector <- c(vector, values)

请注意,在R中,不需要循环遍历向量。 你可以对它们进行整体操作。

此外,这是相当基本的东西,所以你应该通过一些参考

基于OP反馈的更多选项:

 for(i in values) vector <- c(vector, i) 

只是为了完整起见,在for循环中向一个向量附加值并不是真正的R中的哲学。正如@BrodieG指出的那样,通过对向量进行整体运算,R更好。 看看你的代码不能被重写为:

 ouput <- sapply(values, function(v) return(2*v)) 

输出将是一个返回值的向量。 如果值是列表而不是vector,也可以使用lapply

在R中,你可以试试这个方法:

 X = NULL X # NULL values = letters[1:10] values # [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" X = append(X,values) X # [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" X = append(X,letters[23:26]) X # [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "w" "x" "y" "z" 

有时我们不得不使用循环,例如,当我们不知道需要多less次迭代才能得到结果。 以while循环为例。 下面是你绝对应该避免的方法:

 a=numeric(0) b=1 system.time( { while(b<=1e5){ b=b+1 a<-c(a,pi) } } ) # user system elapsed # 13.2 0.0 13.2 a=numeric(0) b=1 system.time( { while(b<=1e5){ b=b+1 a<-append(a,pi) } } ) # user system elapsed # 11.06 5.72 16.84 

这些效率非常低,因为R在每次追加时复制vector。

追加最有效的方法是使用索引。 请注意,这一次我让它迭代1e7次,但它仍然比c更快。

 a=numeric(0) system.time( { while(length(a)<1e7){ a[length(a)+1]=pi } } ) # user system elapsed # 5.71 0.39 6.12 

这是可以接受的。 而且我们可以通过用[[

 a=numeric(0) system.time( { while(length(a)<1e7){ a[[length(a)+1]]=pi } } ) # user system elapsed # 5.29 0.38 5.69 

也许你已经注意到, length可能会很费时间。 如果我们用计数器replacelength

 a=numeric(0) b=1 system.time( { while(b<=1e7){ a[[b]]=pi b=b+1 } } ) # user system elapsed # 3.35 0.41 3.76 

正如其他用户提到的,预先分配vector是非常有帮助的。 但是,如果您不知道需要多less循环来获得结果,则这是速度和内存使用之间的折衷。

 a=rep(NaN,2*1e7) b=1 system.time( { while(b<=1e7){ a[[b]]=pi b=b+1 } a=a[!is.na(a)] } ) # user system elapsed # 1.57 0.06 1.63 

中间的方法是逐渐添加结果块。

 a=numeric(0) b=0 step_count=0 step=1e6 system.time( { repeat{ a_step=rep(NaN,step) for(i in seq_len(step)){ b=b+1 a_step[[i]]=pi if(b>=1e7){ a_step=a_step[1:i] break } } a[(step_count*step+1):b]=a_step if(b>=1e7) break step_count=step_count+1 } } ) #user system elapsed #1.71 0.17 1.89 
 > vec <- c(letters[1:3]) # vec <- c("a","b","c") ; or just empty vector: vec <- c() > values<- c(1,2,3) > for (i in 1:length(values)){ print(paste("length of vec", length(vec))); vec[length(vec)+1] <- values[i] #Appends value at the end of vector } [1] "length of vec 3" [1] "length of vec 4" [1] "length of vec 5" > vec [1] "a" "b" "c" "1" "2" "3"