【问题标题】:Append value to empty vector in R?将值附加到R中的空向量?
【发布时间】:2014-04-09 18:10:34
【问题描述】:

我正在尝试学习 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

【问题讨论】:

  • 为了清楚起见,这不是您在 python 中执行此操作的方式,至少如果我理解正确的话。你可以简单地做vector = values;或者你可以做向量=向量+值。但我可能误解了你的用例

标签: r list vector append


【解决方案1】:

在for循环中附加到一个对象会导致整个对象在每次迭代时都被复制,这导致很多人说“R很慢”,或者“应该避免R循环”。

正如 cmets 中提到的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 &lt;- c() 不是空向量;这是NULL。如果您想要一个空字符向量,请使用vector &lt;- 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 

【讨论】:

  • 我试过这个,但是当我打印(矢量)时得到一个 NULL 列表
  • +1 用于提醒效率低下,但可能会添加有关如何解决的详细信息 (vector &lt;- character(length(values)); for(...)?
  • 如果不鼓励所有人,最好强调一下鼓励的内容,因为这是一种相当普遍的模式。
  • 在这一点上,可能还值得一提的是伟大的书“R inferno”,它讨论了第 2 圈中的增长向量 burns-stat.com/pages/Tutor/R_inferno.pdf
  • 只是片刻,我不确定这是真是假。不过谢谢。
【解决方案2】:

FWIW:类似于 python 的 append():

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

【讨论】:

  • R 中也有 append()。将用作:b &lt;- 1; b &lt;- append(b, 2)。但正如你提到的,c() 是一种更 R 的做事方式。
【解决方案3】:

你有几个选择:

  • c(vector, values)

  • append(vector, values)

  • vector[(length(vector) + 1):(length(vector) + length(values))] &lt;- values

第一个是标准方法。第二个让您可以选择附加到结尾以外的地方。最后一个有点扭曲,但有修改vector的优势(虽然实际上,你可以很容易地修改vector &lt;- c(vector, values)

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

另外,这是相当基本的东西,所以你应该浏览一下 the references

基于 OP 反馈的更多选项:

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

【讨论】:

  • 我正在做一些更复杂的事情。我需要通过 for 循环附加它们,因为我正在修改它们
  • @draconisthe0ry,你为什么不提供更多关于你想要做什么的细节?
  • 哦,我明白了!而不是在 for 循环中执行 c(vector,values[i]) 您必须 "vector = c(vector,values[i])
  • 假设我想使用c 来追加数据帧而不是向量?
【解决方案4】:

只是为了完整起见,在 for 循环中将值附加到向量并不是 R 中的真正理念。正如@BrodieG 指出的那样,R 通过将向量作为一个整体进行操作可以更好地工作。看看你的代码是不是不能改写成:

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

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

【讨论】:

    【解决方案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
    

    【讨论】:

      【解决方案6】:

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

      【讨论】:

        【解决方案7】:
        > 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"
        

        【讨论】:

          【解决方案8】:

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

          【讨论】:

            猜你喜欢
            • 2015-03-31
            • 1970-01-01
            • 2010-10-21
            • 2023-04-01
            • 2015-05-13
            • 1970-01-01
            • 1970-01-01
            • 2019-04-09
            • 1970-01-01
            相关资源
            最近更新 更多