R:数据表中按行的条件总和

R: Conditional Sum by Row in DataTable

我有一个非常大的数据集(数百万行,我需要循环数千次),在循环期间我必须做一个条件求和,这似乎需要很长时间。有没有办法提高效率?

数据table格式如下:

DT <- data.table('A' = c(1,1,1,2,2,3,3,3,3,4),
                 'B' = c(500,510,540,500,540,500,510,519,540,500),
                 'C' = c(10,20,10,20,10,50,20,50,20,10))
一个 B C
1 500 10
1 510 20
1 540 10
2 500 20
2 540 10
3 500 50
3 510 20
3 519 50
3 540 20
4 500 10

我需要 C 列(在新列 D 中)的总和,A == A,并且 B >= B & B < B + 20(按行)。所以输出 table 将如下所示:

一个 B C D
1 500 10 30
1 510 20 30
1 540 10 10
2 500 20 20
2 540 10 10
3 500 50 120
3 510 20 120
3 519 50 120
3 540 20 20
4 500 10 10

我目前使用的代码:

DT[,D:= sum(DT$C[A == DT$A & ((B >= DT$B) & (B < DT$B + 20))]), by=c('A', 'B')]

这需要很长时间才能真正 运行,并且给了我错误的答案。我得到的输出如下所示:

一个 B C D
1 500 10 10
1 510 20 30
1 540 10 10
2 500 20 20
2 540 10 10
3 500 50 50
3 510 20 70
3 519 50 120
3 540 20 20
4 500 10 10

(即 D 似乎只是累积增加)。

我不太关心累积的事情,更关心速度。最终我想要得到的是 A 的 C 的最大总和,前提是 B 在彼此的 20 以内。我真的很感激任何帮助!提前致谢。

# logic for B
DT[, g := B >= shift(B) & B < shift(B, 1) + 20, by = A]
# creating index column
DT[, gi := !g] 
DT[is.na(gi), gi := T]
DT[, gi := cumsum(gi)]
DT[, D := sum(C), by = gi] # summing by new groups
DT
#     A   B  C     g gi   D
#  1: 1 500 10    NA  1  30
#  2: 1 510 20  TRUE  1  30
#  3: 1 540 10 FALSE  2  10
#  4: 2 500 20    NA  3  20
#  5: 2 540 10 FALSE  4  10
#  6: 3 500 50    NA  5 120
#  7: 3 510 20  TRUE  5 120
#  8: 3 519 50  TRUE  5 120
#  9: 3 540 20 FALSE  6  20
# 10: 4 500 10    NA  7  10

您可能需要调整 B 的逻辑,因为问题中的所有边缘情况都不清楚...如果对于一个 A 值,我们有 c(30, 40, 50, 60),所有这些行中的一组?

如果我没理解错的话,这可以通过非equi自连接来解决:

DT[, Bp20 := B + 20][
  DT, on = .(A, B >= B, B < Bp20), mult = "last"][
    , .(B, C = i.C, D = sum(i.C)), by = .(A, Bp20)][
      , Bp20 := NULL][]
    A   B  C   D
 1: 1 500 10  30
 2: 1 510 20  30
 3: 1 540 10  10
 4: 2 500 20  20
 5: 2 540 10  10
 6: 3 500 50 120
 7: 3 510 20 120
 8: 3 519 50 120
 9: 3 540 20  20
10: 4 500 10  10