按data.table列A分组,计算列A≥分组值时其他列的累计和
问题描述
有一个多行多列的data.table,第一列A为索引列,其余列为数值列。需要按列A分组,计算所有A值大于等于当前分组值的行中,各数值列的求和结果(即从当前行到最后一行的列值总和)。
示例数据
原始data.table如下:
A B C <int> <int> <int> 1: 1 15 14 2: 2 9 9 3: 3 12 11 4: 4 1 19 5: 5 11 13
示例数据定义代码:
dt <- structure( list( A = 1:5, B = c(15L, 9L, 12L, 1L, 11L), C = c(14L, 9L, 11L, 19L, 13L) ), row.names = c(NA, -5L), class = c("data.table", "data.frame") )
预期结果
计算后得到的结果:
A B C <int> <int> <int> 1: 1 48 66 2: 2 33 52 3: 3 24 43 4: 4 12 32 5: 5 11 13
尝试过的代码
用户尝试了以下代码,但不知道如何批量应用到多列:
dt[, .(B = sum(dt$B[.I:nrow(dt)]), C = sum(dt$C[.I:nrow(dt)])), by = .(A)]
解决方案
方法1:反向累计求和(高效推荐)
利用reverse+cumsum实现反向累计求和,无需逐行循环,效率更高:
# 自动排除索引列A,批量处理所有数值列 dt[, (setdiff(names(dt), "A")) := lapply(.SD, function(x) rev(cumsum(rev(x)))), .SDcols = setdiff(names(dt), "A")]
如果只需指定特定列,修改.SDcols为目标列名列表即可,比如.SDcols = c("B", "C")。
方法2:逐行范围求和(贴合原始思路)
沿用行索引定位的思路,用lapply批量处理多列:
dt[, c("B", "C") := lapply(.SD, function(col) { sapply(.I, function(i) sum(col[i:.N])) }), .SDcols = c("B", "C")]
其中.N是data.table内置的当前数据集行数,替代nrow(dt)更符合语法习惯。
方法3:按A分组筛选求和
严格贴合“按A分组”的需求逻辑,通过分组键值筛选行求和:
dt[, c("B", "C") := lapply(.SD, function(col) { sum(col[A >= .BY$A]) }), by = A, .SDcols = c("B", "C")]
.BY代表当前分组的A值,通过A >= .BY$A筛选符合条件的行并求和。
内容的提问来源于stack exchange,提问作者user16196
相关产品推荐
相关产品推荐

