【发布时间】:2023-01-29 21:27:35
【问题描述】:
我有一个 data.table,我想按组(客户 ID)汇总并查看他们的第一次支出与第二次支出、第三次支出等的比较。
选择例如第一行使用.SD[1]分组:
agg_dt <- dt[ , .SD[1], by = customer_id]
给出了一个非常快的结果(对于具有 500 万行以上的数据集,只需 1.94 秒)。
但是,如果我将索引号(此处为 1)放入一个变量(我想这样做,以便我可以将其转换为一个可以用不同数字重复调用的函数),它会突然变慢很多(5.23 分钟)。
number_var <- 1
agg_dt <- dt[ , .SD[number_var], by = customer_id]
就我而言,直接使用数字和通过变量使用数字应该没有区别,那么是什么原因造成的,我该如何解决呢?
为了完整展示代码,我在 kaggle 上做了一个玩具示例:
https://www.kaggle.com/code/keithcooper/data-table-weird-result/notebook
它要小得多,但即使在那里,差异也是 0.00995 秒到 2.71042 秒。
【问题讨论】:
-
不完全是 this one 的副本,但很接近。
dt[dt[, .I[number_var], by = customer_id]$V1]似乎是最快的选择。这比不必评估行号时慢 3 倍。 -
那更快。但是将数字作为变量传递仍然会使时间加倍。知道为什么吗?
-
我没有确定的答案。
[.data.table做了很多。在您的示例中,它将首先尝试使用 data.table 中的变量,并且看到它不存在,它将测试下一个环境(这里是“全局”环境)。为什么dt[dt[, .I等更快,这让我很困惑。理论上它会假设做得更多,但可能优化得更好。 -
所以它认为变量是一个 data.table 对象并且每次都试图查找它?
-
在
[.data.table中使用verbose = TRUE,你会发现d[ , .SD[1], by = g, verbose = TRUE]是GForce优化的,而d[ , .SD[ix], by = g, verbose = TRUE]不是。另见?datatable.optimize。
标签: r performance data.table subset