R语言中使用data.table实现分组唯一值求和
需求背景
- 已定义
data.table结构数据集dt,完整结构代码如下:
dt <- structure(list(group = c("A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B"), V1 = c(6.38, 6.38, 6.38, 6.38, -1.53, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -24.93, -6.8, -6.8, -6.8, -6.8, -6.8, -1.71, -1.71, -1.71, -1.71, -1.71, -1.06, -1.06, -1.06, -1.06, -1.06, -1.06, -1.06, -1.06, -1.06, -1.06, -1.06, -1.06, -1.06, -1.06, -1.06, -1.06, -1.06, -1.06, -1.06, -1.06, -1.06, -1.06, -1.06, -1.06, -1.06, -1.06, -1.06, -1.06, -1.06, -1.06, -1.06, -1.06, -1.06, -1.06, -1.06, -1.06, -1.06, 8.42, 8.42, 8.42, 4.34, 4.34, 4.34, 4.34, 4.34, 4.34, 4.34, 4.34, 4.34, 4.34, 4.34, 4.34, 4.34, 4.34, 4.34, 4.34, 4.34, 4.34), V2 = c(0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, -0.11, -0.11, -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, 1.6, 1.6, 1.6, 1.6, -0.55, -0.55, -0.55, -2.15, -2.15, -2.15, -2.15, -2.15, -2.15, -2.15, -2.15, -2.15, -0.19, -0.19, -0.19, -0.19, -0.19, 2.63, 2.63, 2.63, 2.63, 2.63, 2.63, 2.63, 2.63, 2.63, 2.63, 2.63, 2.63, 2.63, 2.63, 2.63, 2.63, -3.86, -3.86, 0.48, 0.48, 0.48, 0.48, 0.48, 0.48, 0.48, -1.38, -1.38, -1.38, -1.38, -5.15, -11.58, -11.58, -11.58, -11.58, -11.58, -11.58, -11.58, -11.58, -11.58, -0.46, -7.32, -7.32, -7.32, -7.32, -7.32, -7.32, -7.32, -7.32, 2.67, 4.88, 4.88, 4.88, 4.88, 4.88, 4.88, 4.88, 4.88, -11.57, -11.57, -11.57, 1.67, 1.55, 1.55, 2.3, 2.3, 2.3, 2.3, 2.3, 2.3, 2.3, 2.3, -1.42, 21.88, 21.88, 21.88, 21.88, 21.88, 21.88, 21.88, 21.88, 21.88, 21.88, 21.88, 21.88, 21.88, 21.88, 21.88, 21.88, 21.88, 21.88, -0.59, -0.59, -0.59, -0.59, -0.59, -1.87, -1.87, -1.87)), row.names = c(NA, -138L), class = c("data.table", "data.frame"))
- 核心需求:按照
group列分组,对V1、V2两列分别计算组内去重后的唯一值总和
现有实现的问题
- 原代码直接对全列值求和,重复值会被多次累计,无法得到去重后的结果
- 原代码如下:
library(data.table) dt[, lapply(.SD, sum, na.rm = T), by=group, .SDcols = c("V1", "V2")]
- 原代码输出结果:
group V1 V2 1: A -1571.53 -88.67 2: B 20.55 245.64
预期输出效果
group V1 V2 1: A -269.38 -12.43 2: B -4.47 27.17
调整后的正确实现
- 核心逻辑:对每一个分组内的目标列,先通过
unique()提取不重复值,再执行求和操作 - 调整后代码:
library(data.table) dt[, lapply(.SD, function(col) sum(unique(col), na.rm = TRUE)), by = group, .SDcols = c("V1", "V2")]
- 代码说明:
- 保留原有按
group分组、通过.SDcols指定计算列的逻辑 - 替换原有直接调用
sum的逻辑,嵌套unique()先做组内去重 - 保留
na.rm = TRUE参数,兼容列内存在空值的场景
- 保留原有按
内容的提问来源于stack exchange,提问作者Saurabh
相关产品推荐
相关产品推荐

