向R中的空向量追加值?

lf3rwulv  于 2022-12-27  发布在  其他
关注(0)|答案(9)|浏览(175)

我正在学习R,但我不知道如何追加到列表中。
如果这是巨蟒,我会......

#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
xmakbtuz

xmakbtuz1#

在for循环中追加对象会导致整个对象在每次迭代时都被复制,这会导致很多人说"R太慢",或者"应该避免R循环"。
正如评论中提到的BrodieG:最好预先分配所需长度的向量,然后在循环中设置元素值。
这里有几种向向量添加值的方法。所有这些方法都是不推荐的。

追加到循环中的向量

# 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()

循环前预分配向量

如果你绝对必须使用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
j5fpnvbx

j5fpnvbx2#

FWIW:类似于python的append():

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

watbbzwu3#

您有几个选项:

  • 第一个月
  • 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)
qc6wkl3g

qc6wkl3g4#

为了完整起见,在for循环中向向量添加值并不是R的真正理念。正如@BrodieG指出的那样,R将向量作为一个整体来操作效果更好。看看你的代码是否可以重写为:

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

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

dfuffjeb

dfuffjeb5#

有时候我们不得不使用循环,例如,当我们不知道需要多少次迭代才能得到结果时,以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每次追加时都会复制向量。
最有效的追加方法是使用index,注意这次我让它迭代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
yrwegjxp

yrwegjxp6#

在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"
mm9b1k5b

mm9b1k5b7#

> 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"
ulydmbyx

ulydmbyx8#

你在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))
v8wbuo2f

v8wbuo2f9#

在R中,您创建了一个“列表”,它执行以下操作:
v <- numeric()(是一个数值向量,在Python中是int)
v <- character()(字符向量,Python中为字符串)
那么,如果你想添加一个值,你必须这样做:
v[1] <- 10(附加到向量“v”,在位置“1”中值10)
v[2] <- 11(将值11附加到向量“v”的位置“2”)
所以,如果你想在for循环中追加多个值,试试这个:

v <- numeric()

for (value in 1:10) {

    v[value] <- value
    
}

v

[1]  1  2  3  4  5  6  7  8  9 10

相关问题