r - 为什么 DT1[DT2][, value1-value] 在列较少的 data.table 上比 DT1[DT2, value1-value] 快?

标签 r data.table

这与这个问题( Can I access repeated column names in `j` in a data.table join? )有关,之所以问这个问题是因为我认为与此相反的是真的。

data.table 只有 2 列:

假设你想加入两个 data.tables然后对两个连接的列执行一个简单的操作,这可以通过一次或两次调用 .[ 来完成。 :

N = 1000000
DT1 = data.table(name = 1:N, value = rnorm(N))
DT2 = data.table(name = 1:N, value1 = rnorm(N))
setkey(DT1, name)

system.time({x = DT1[DT2, value1 - value]})     # One Step

system.time({x = DT1[DT2][, value1 - value]})   # Two Step

原来打了两个电话 - 先做连接,然后做减法 - 明显比一次性快 .
> system.time({x = DT1[DT2, value1 - value]})
   user  system elapsed 
   0.67    0.00    0.67 
> system.time({x = DT1[DT2][, value1 - value]})
   user  system elapsed 
   0.14    0.01    0.16 

为什么是这样?

具有许多列的数据表:

如果您将很多列放入 data.table那么你最终会发现一步法更快 - 大概是因为 data.table仅使用您在 j 中引用的列.
N = 1000000
DT1 = data.table(name = 1:N, value = rnorm(N))[, (letters) := pi][, (LETTERS) := pi][, (month.abb) := pi]
DT2 = data.table(name = 1:N, value1 = rnorm(N))[, (letters) := pi][, (LETTERS) := pi][, (month.abb) := pi]
setkey(DT1, name)
system.time({x = DT1[DT2, value1 - value]})
system.time({x = DT1[DT2][, value1 - value]})

> system.time({x = DT1[DT2, value1 - value]})
   user  system elapsed 
   0.89    0.02    0.90 
> system.time({x = DT1[DT2][, value1 - value]})
   user  system elapsed 
   1.64    0.16    1.81 

最佳答案

我认为这是由于重复子集DT1[DT2, value1-value]为每个 nameDT2 .也就是说,您必须执行 j每个操作i在这里,而不是只有一个 j操作后join .对于 1e6 唯一条目,这变得非常昂贵。即,[.data.table变得重要和引人注目。

DT1[DT2][, value1-value] # similar to rowSums
DT1[DT2, value1-value]

在第一种情况下,DT1[DT2] ,您执行 join首先,它真的很快。当然,正如您所展示的,随着列数的增加,您会看到不同之处。但重点是执行一次连接。但在第二种情况下,您将按 DT2 的名称对 DT1 进行分组,并且您正在计算其中的每一个的差异。也就是说,您正在对 DT1 进行子集化对于 DT2 的每个值- 每个子集一个 'j' 操作!你可以通过运行这个来更好地看到这一点:
Rprof()
t1 <- DT1[DT2, value1-value]
Rprof(NULL)
summaryRprof()

# $by.self
#                self.time self.pct total.time total.pct
# "[.data.table"      0.96    97.96       0.98    100.00
# "-"                 0.02     2.04       0.02      2.04

Rprof()
t2 <- DT1[DT2][, value1-value]
Rprof(NULL)
summaryRprof()

# $by.self
#                self.time self.pct total.time total.pct
# "[.data.table"      0.22    84.62       0.26    100.00
# "-"                 0.02     7.69       0.02      7.69
# "is.unsorted"       0.02     7.69       0.02      7.69

当您有太多列和 join 时,重复子集的这种开销似乎可以克服。在许多列上超车作为耗时的操作。您可能可以通过分析其他代码自己检查一下。

关于r - 为什么 DT1[DT2][, value1-value] 在列较少的 data.table 上比 DT1[DT2, value1-value] 快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17719480/

相关文章:

r - 计算 R 中数据框中每对分类单元之间的差异性

r - 导入使用 .zstd 压缩的数据文件

r - Ubuntu 在 R 中删除 .libPaths()

python - MLWIC : Machine Learning for Wildlife Image Classification in R Issues with Python

R:将带有列表的数据框输出到csv

r - 为另一个 data.table 列中的每个值外观检查一个 data.table 列中所有元素的最快方法

r - R 中 data.tables 的 cut 函数的替代方案 - 因子的整数变量

r - 在 data.table 中按组绘制

r - 查找功能的帮助引用页时如何指定软件包?

r - Append\Union 两个或几个表为一个