【问题标题】:How to insert elements into a vector?如何将元素插入向量中?
【发布时间】:2010-12-02 09:54:10
【问题描述】:

我有一个逻辑向量,我希望在特定索引处插入新元素。我在下面想出了一个笨拙的解决方案,但是有没有更简洁的方法?

probes <- rep(TRUE, 15)
ind <- c(5, 10)
probes.2 <- logical(length(probes)+length(ind))
probes.ind <- ind + 1:length(ind)
probes.original <- (1:length(probes.2))[-probes.ind]
probes.2[probes.ind] <- FALSE
probes.2[probes.original] <- probes

print(probes)

给予

[1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE

和

print(probes.2)

给予

[1]  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE
[13]  TRUE  TRUE  TRUE  TRUE  TRUE

所以它可以工作,但看起来很丑 - 有什么建议吗?

【问题讨论】:

  • 为什么需要插入?
  • 长话短说,但基本上是在寻找 TRUE 的运行,但有预定的地方我想中断运行。我第一次使用“rle”,但它的扩展性很差,所以想出了这个脏矢量解决方案

标签: r


【解决方案1】:

嗯,嗨,我也有同样的疑问,但我无法理解人们的回答,因为我还在学习语言。所以我试着自己做,我想它可以工作!我创建了一个向量,我想在第 3、第 5 和第 6 个索引之后插入值 100。这是我写的。

vector <-  c(0:9)
indexes <-  c(6, 3, 5)
indexes <- indexes[order(indexes)]
i <-  1
j <-  0

while(i <= length(indexes)){
  vector <- append(vector, 100, after = indexes[i] + j)
  i <-i + 1
  j <- j + 1
}
vector

向量“索引”必须按升序排列才能正常工作。这就是为什么我把它们放在第三行的原因。 变量“j”是必要的,因为在每次迭代中,新向量的长度都会增加并且原始值会移动。 如果您希望将新值并排插入,只需重复索引编号即可。例如,通过分配索引

【讨论】:

    【解决方案2】:

    在上面 Wojciech 的答案的基础上,我想出了一个易于理解且运行速度相当快的好答案。我将针对此处的示例调整该方法,但它可以很容易地推广到几乎任何数据类型的缺失点的任意模式(如下所示)。

    probes <- rep(TRUE, 15)
    ind <- c(5,10)
    
    probes.final <- rep(FALSE, length(probes)+length(ind))
    probes.final[-ind] <- probes
    

    我需要的数据是定期采样的,但是很多样本被丢弃了,生成的数据文件只包含那些保留的时间戳和测量值。我需要生成一个包含所有时间戳的向量和一个插入了 NA 的数据向量,用于丢弃的时间戳。我使用了从here 偷来的“not in”功能,让它更简单一些。

    `%notin%` <- Negate(`%in%`)
    dat <- rnorm(50000) # Data given
    times <- seq(from=554.3, by=0.1, length.out=70000] # "Original" time stamps
    times <- times[-sample(2:69999, 20000)] # "Given" times with arbitrary points missing from interior
    
    times.final <- seq(from=times[1], to=times[length(times)], by=0.1)
    na.ind <- which(times.final %notin% times)
    dat.final <- rep(NA, length(times.final))
    dat.final[-na.ind] <- dat
    

    【讨论】:

      【解决方案3】:

      或者您可以使用 miscTools 包中的 insertRow 函数来执行此操作。

      probes <- rep(TRUE, 15)
      ind <- c(5,10)
      for (i in ind){
          probes <- as.vector(insertRow(as.matrix(probes), i, FALSE))
      }
      

      【讨论】:

      • 我来这里是为了找那个。使用名称进行排序的技巧很酷,加深了我对语言的理解,但这更适合我的情况。
      【解决方案4】:
      probes <- rep(TRUE, 1000000)
      ind <- c(50:100)
      val <- rep(FALSE,length(ind))
      
      new.probes <- vector(mode="logical",length(probes)+length(val))
      new.probes[-ind] <- probes
      new.probes[ind] <- val
      

      一些时间安排: 我的方法 用户系统已过 0.03 0.00 0.03

      马立克法 用户系统已过 0.18 0.00 0.18

      R 附加 for 循环 用户系统已过 1.61 0.48 2.10

      【讨论】:

      • 好主意,似乎是最有效的方法!但是,您需要移动所有索引才能使其按预期工作,即在分配给new.probes 之前添加ind &lt;- ind + 0:(length(ind)-1)。
      • 您可以省略最后一步(以及val 的定义),只需用要替换的值初始化new.probes:new.probes &lt;- rep(FALSE,length(probes)+length(val))。这使它更快。
      • -1 如果它是正确的,那将是一个很好的答案。您需要ind &lt;- ind + seq_len(length(ind))(1:length(ind),而不是第一条评论中的 0)。并且logical(length(probes)+length(val)) 或rep(FALSE, length(probes)+length(val)) 比vector(mode=... 更神秘。
      【解决方案5】:

      这些都是非常有创意的方法。我认为使用索引绝对是要走的路(Marek 的解决方案非常好)。

      我只想提一下,有一个函数可以大致做到这一点:append()。

      probes <- rep(TRUE, 15)
      probes <- append(probes, FALSE, after=5)
      probes <- append(probes, FALSE, after=11)
      

      或者您可以使用索引递归地执行此操作(您需要在每次迭代中增加“后”值):

      probes <- rep(TRUE, 15)
      ind <- c(5, 10)
      for(i in 0:(length(ind)-1)) 
          probes <- append(probes, FALSE, after=(ind[i+1]+i))
      

      顺便说一句,this question was also previously asked on R-Help。正如巴里所说:

      “实际上我会说没有办法做到这一点,因为我认为你实际上不能插入向量中——你必须创建一个新的向量来产生插入的错觉!”

      【讨论】:

      • 我不知道 append 功能,感谢您提醒我!我应该在我的问题中指定我不想要循环,因为我的真实向量将包含数千/数百万个元素
      • 并且可以设置after = 0在向量的开头插入一个新值。
      • 如果ind 被排序,正如你所假设的那样,你可以更简单地反向执行循环:for(i in length(ind):1) append(..., after=ind[i]) 吗?
      【解决方案6】:

      你可以用索引做一些魔法:

      首先创建带有输出值的向量:

      probs <- rep(TRUE, 15)
      ind <- c(5, 10)
      val <- c( probs, rep(FALSE,length(ind)) )
      # > val
      #  [1]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
      # [13]  TRUE  TRUE  TRUE FALSE FALSE
      

      现在把戏。每个旧元素获得排名,每个新元素获得半排名

      id  <- c( seq_along(probs), ind+0.5 )
      # > id
      #  [1]  1.0  2.0  3.0  4.0  5.0  6.0  7.0  8.0  9.0 10.0 11.0 12.0 13.0 14.0 15.0
      # [16]  5.5 10.5
      

      然后使用order按正确顺序排序:

      val[order(id)]
      #  [1]  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE
      # [13]  TRUE  TRUE  TRUE  TRUE  TRUE
      

      【讨论】:

      • 漂亮又狡猾 - 数千/数百万个元素的订单规模如何?
      • 在 1.58GHz Core2 system.time(order(rnorm(1e6))) 需要
      • 这很优雅,马雷克!
      【解决方案7】:

      这个怎么样:

      > probes <- rep(TRUE, 15)
      > ind <- c(5, 10)
      
      > probes.ind <- rep(NA, length(probes))
      > probes.ind[ind] <- FALSE
      > new.probes <- as.vector(rbind(probes, probes.ind))
      > new.probes <- new.probes[!is.na(new.probes)]
      > new.probes
       [1]  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE
      [13]  TRUE  TRUE  TRUE  TRUE  TRUE
      

      【讨论】:

      • 偷偷摸摸!使用 as.vector 对 rbind 创建的矩阵进行逐列折叠的事实。这是因为矩阵只是一个带有指示行数的附加信息的向量,并且在内部按列顺序存储。这是 R 语言定义的一部分,但可能有点晦涩难懂,具体取决于阅读代码的人...
      • @Harlan 很好的解释。在处理这个例子时,这会产生很大的不同。
      【解决方案8】:

      这有点棘手。这是一种方法。它遍历列表,每次都插入,所以效率不是很高。

      probes <- rep(TRUE, 15)
      probes.ind <- ind + 0:(length(ind)-1)
      for (i in probes.ind) {
        probes <- c(probes[1:i], FALSE, probes[(i+1):length(probes)])
      }
      
      > probes
       [1]  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE
      [13]  TRUE  TRUE  TRUE  TRUE  TRUE
      

      如果 ind 有重复的元素,这甚至应该可以工作,尽管需要对 ind 进行排序才能使 probes.ind 构造工作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-04-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-11-26
        • 2021-02-10
        • 1970-01-01
        相关资源
        最近更新 更多