You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

按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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 21:12:14