我正在尝试学习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
答案 0 :(得分:167)
以下是几种方法。所有人都气馁。附加到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 <- character()
。
另请注意,正如BrodieG在评论中指出:如果绝对必须使用for循环,那么至少在循环之前预先分配整个向量。这比追加更大的向量要快得多。
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
答案 1 :(得分:54)
FWIW:类似于python的append():
b <- 1
b <- c(b, 2)
答案 2 :(得分:24)
您有几个选择:
c(vector, values)
append(vector, values)
vector[(length(vector) + 1):(length(vector) + length(values))] <- values
第一个是标准方法。第二个允许您选择追加除结尾之外的某个位置。最后一个有点扭曲,但具有修改vector
的优点(尽管如此,你可以轻松地vector <- c(vector, values)
。
请注意,在R中,您不需要循环向量。你可以整体操作它们。
此外,这是相当基本的内容,因此您应该浏览一些 the references 。
基于OP反馈的更多选项:
for(i in values) vector <- c(vector, i)
答案 3 :(得分:14)
仅仅为了完整性,将值附加到for循环中的向量并不是R中的哲学。通过对整个向量进行操作,R的效果更好,正如@BrodieG所指出的那样。看看您的代码是否可以重写为:
ouput <- sapply(values, function(v) return(2*v))
输出将是返回值的向量。如果值是列表而不是向量,您也可以使用lapply
。
答案 4 :(得分:5)
有时我们必须使用循环,例如,当我们不知道获得结果需要多少次迭代时。以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会在每次附加时复制矢量。
最有效的追加方式是使用索引。请注意,这次我让它迭代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
可能非常耗时。如果我们用计数器替换length
:
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
正如其他用户所提到的,预先分配矢量非常有用。但是,如果您不知道获得结果需要多少循环,这是速度和内存使用之间的权衡。
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
答案 5 :(得分:2)
在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"
答案 6 :(得分:2)
> 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"
答案 7 :(得分:0)
您在python代码中使用的是python中的列表,如果我想得到的话,它与R向量完全不同:
# you can do like this if you'll put them manually
v <- c("a", "b", "c")
# if your values are in a list
v <- as.vector(your_list)
# if you just need to append
v <- append(v, value, after=length(v))