【问题标题】:Add a row by reference at the end of a data.table object在 data.table 对象的末尾通过引用添加一行
【发布时间】:2013-05-23 10:06:53
【问题描述】:

在这个question 中,data.table 包创建者解释了为什么行不能通过中间的引用插入(或删除)data.table。他还指出,这种操作可能在表格的末尾。您能否显示执行此操作的代码?这将是

的“参考”版本
a<- data.table(id=letters[1:2], var=1:2)
> a
   id var
1:  a   1
2:  b   2
> rbind(a, data.table(id="c", var=3))
   id var
1:  a   1
2:  b   2
3:  c   3

谢谢。

编辑:

由于尚无法找到合适的解决方案,从速度和内存使用的角度来看,以下哪一项更好(如果内部不同,则不确定)?

rbind(a, data.table(id="c", var=3))

rbindlist(list(a,  data.table(id="c", var=3)))

最终还有其他(更好的)方法吗?

【问题讨论】:

  • 抱歉,尚未实施。该答案中的“可能”和“将是”这两个词是将来时的意思。
  • @MatthewDowle 嗨。我明白了,您的意思是速度(与 SQL 相比)并说“可以在最后插入(和删除),立即”作为一种可能性......对不起我的错。我将对问题进行更改以使其更有意义。
  • 任何人在 DT 处理中添加这样的行?如下所示: DT[,transformation][,transformation2][,transformation3][,transformation4,by='abc'][add_grand_total_summary_row] 将总计放在附加列中很容易,但它并不那么优雅。
  • @MattDowle 你能至少添加一个tracking FR 以便我们检查是否有版本承诺?

标签: r data.table


【解决方案1】:

要回答您的编辑,只需运行基准测试:

a = data.table(id=letters[1:2], var=1:2)
b = copy(a)
c = copy(b) # let's also just try modifying same value in place
            # to see how well changing existing values does
microbenchmark(a <- rbind(a, data.table(id="c", var=3)),
               b <- rbindlist(list(b,  data.table(id="c", var=3))),
               c[1, var := 3L],
               set(c, 1L, 2L, 3L))
#Unit: microseconds
#                                                  expr     min        lq    median        uq      max neval
#          a <- rbind(a, data.table(id = "c", var = 3)) 865.460 1141.2585 1357.1230 1539.4300 6814.492   100
#b <- rbindlist(list(b, data.table(id = "c", var = 3))) 260.440  325.3835  445.4190  522.8825 1143.930   100
#                                   c[1, `:=`(var, 3L)] 482.147  626.5570  778.3135  904.3595 1109.539   100
#                                    set(c, 1L, 2L, 3L)   2.339    5.677    7.5140    9.5170   19.033   100

rbindlist 明显优于rbind。感谢 Matthew Dowle 指出在循环中使用 [ 的问题,我添加了另一个使用 set 的基准。

从上面你最好的选择是使用rbindlist,或者调整data.table的大小,然后只填充值(你也可以在C++中使用与std::vector类似的策略,然后加倍每次空间用完时的大小,如果您不知道要开始的数据大小,然后在完成填充后,删除多余的行)。

【讨论】:

  • 不错。令人惊讶的是,这可能是多次调用[.data.table 的开销,因为在此示例中microbenchmark 调用了它100 次。尝试使用 set() 代替可循环的 :=
  • 如果您将id 设置为c 的键并且您将c[1, var := 3L] 更改为c["a", var := 3L],则这个比第一个更慢。无论如何,非常感谢。我知道我可以自己完成,但我对data.table 还很陌生,我想从这个问题中得到最大的收获(例如,我不知道copy!)
  • @Matthew Dowle 比 rbindlist 快 25%
  • 不知道这些年来set() 的功能是否发生了变化,但是当前代码不是在原始数据上附加一行而是更新单个值...不要这么认为2019年可以加行。
  • @snoram 它在 2013 年也没有 :) 您可以查看编辑历史以了解为什么将 set 添加到基准测试中 - 基本上它提供了一个下限。
猜你喜欢
  • 2022-12-01
  • 1970-01-01
  • 2022-11-28
  • 2017-06-22
  • 2023-03-07
  • 2017-10-14
  • 1970-01-01
  • 2011-01-06
相关资源
最近更新 更多