数据表中大面板按行操作的性能问题

Performance issues with large panel row-wise operation in datatable

这是一个后续问题。我有以下面板数据:

library(data.table)
set.seed(1)
time=rep(seq(as.Date("2001-01-31"), as.Date("2050-01-31"), by="years"))
nrOfIDs <- 10000
groupvars <- letters[1:5]
DT <- data.table(time=rep(time,nrOfIDs),
             ind=rep(1:nrOfIDs,each=length(time)),
             x=sample(nrOfIDs*length(time)),
             y=sample(nrOfIDs*length(time)),
             group=rep(groupvars,each=(nrOfIDs*length(time))/length(groupvars)))


nrow(DT) # 500000

简而言之,我想要做的是,对于每个 ID,获取“x”列中的每个值,并将“y”列中的所有现有值添加到它。这必须在每个“组”的数据集中单独完成。 例如,对于 x1,我需要计算 x1 + y1、x1 + y2、x1 + y3 等等。然后对 x2、x3、x4 等相同。在每种情况下,始终将所有可能的 y 值添加到相应的 x 值。

我收到了几个关于如何执行此操作的答案(请参阅:),但它们不适用于我的数据集。问题是它爆炸了。举例来说,在上面的代码中,我使用了nrOfIDs <- 10000。这可以进一步增加以更接近我的实际问题,但代码已经不适用于这个数字。例如,使用带有以下代码的交叉连接:

DT[, CJ(x, y, sorted = FALSE), by = .(ind,group)]

给出:Error in [.data.table(DT, , CJ(x, y, sorted = FALSE), by = .(time, group)) : negative length vectors are not allowed

原因是结果行太多。例如,如果我们使用:

DT[, CJ(x, y, sorted = FALSE), by = .(group)]

我们得到:Error in CJ(x, y, sorted = FALSE) : Cross product of elements provided to CJ() would result in 10000000000 rows which exceeds .Machine$integer.max == 2147483647

所以这似乎是一个性能问题,但不仅如此。

最后我只是在寻找每个结果对的最低总和。假设 x1 与 y1 的总和为 2,x1 与 y2 的总和为 3,等等,所有其他总和 > 2。因此在这种情况下我只需要保存 x1 与 y1 的总和。但要实现这一点,我们也需要中间结果。所以我不确定如何在不使数据集变大的情况下做到这一点。

我会提供任何提示。我不确定,但在我看来,对于更大的数据集,这只能通过循环 ID 来解决?

这里可能遗漏了什么,但是...

f <- \(x, y) {sapply(as.data.table(outer(y,x,'+')), min)}
DT[, .(result = f(x, y)), by=.(group, ind)]
##     group   ind result
##  1:     a     1  24664
##  2:     a     1 453013
##  3:     a     1 124689
##  4:     a     1 436799
##  5:     a     1 332006

这在我的机器上运行 3.9 秒。