如何借助data.table加速分组值的归一化处理
data.table分组缩放计算的速度优化问题
我正在尝试加速对data.table对象的特定计算。该表包含一个value列和一个或多个分组列,需求是:对每个分组组合,若组内value的总和大于1,就按比例缩小这些值,使其总和变为1;若总和不大于1,则保持原值不变。可以假设所有value均为非负。
示例数据设置(50万行)
library(data.table) n_rows <- 5e5 dt <- data.table( # 分组变量 group1 = sample(letters, size = n_rows, replace = TRUE), group2 = sample(letters, size = n_rows, replace = TRUE), group3 = sample(letters, size = n_rows, replace = TRUE), group4 = sample(letters, size = n_rows, replace = TRUE), # 非负数值列 value = runif(n_rows) )
初始解决方案
scale_values <- function(values) { values / sum(values) } dt[, {value := if (sum(value) > 1) { scale_values(value) } else { value }}, by = list(group1, group2, group3, group4)]
这是我尝试多种data.table语法和scale_values替代实现后找到的最快方案,但实际场景中数据表会有约2000万行数据和5个分组列,希望能进一步提升速度。
补充:两步法优化
后来发现分两步处理的速度快得多:
dt[, sum_values := sum(value), by = list(group1, group2, group3, group4)][ sum_values > 1, value := scale_values(value), by = list(group1, group2, group3, group4)]
但我不太清楚这种两步法速度更快的原因,希望能得到解释。
内容的提问来源于stack exchange,提问作者weakCoder
相关产品推荐
相关产品推荐

