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

只有两列的data.table:

假设您希望联接两个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中,那么您最终会发现一步方法更快-大概是因为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]中的每个name重复设置了DT2所致。也就是说,您必须在此处为每个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 - 为什么在具有较少列的data.table上,DT1 [DT2] [,value1-value]比DT1 [DT2,value1-value]快?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17719480/

10-11 01:01