data.table连接时引用i表任意列计算加权均值的优化方案
data.table关联计算按行加权均值优化方案
核心实现逻辑
直接使用data.table的update join语法,不需要生成任何中间表,可直接在原DT1中新增计算结果列,同时解决i表列读取的问题。
前置示例数据
library(data.table) # DT1:k2为关联键,v1/v2/v3为待计算数值列(列数可动态调整) DT1 <- data.table(k2 = 1:5, v1 = rnorm(5), v2 = rnorm(5), v3 = rnorm(5)) # DT2:k2为关联键,w1/w2/w3为对应权重列 DT2 <- data.table(k2 = 1:5, w1 = runif(5), w2 = runif(5), w3 = runif(5)) # 动态指定列组,无需硬编码列名 val_cols <- grep("^v", names(DT1), value = TRUE) # 待计算数值列,可自定义匹配规则 w_cols <- grep("^w", names(DT2), value = TRUE) # 对应权重列,顺序需和val_cols一一对应
方案1:逐行计算(逻辑清晰,适合中小数据量)
DT1[DT2, weighted_avg := { vals <- unlist(mget(val_cols)) weights <- unlist(mget(paste0("i.", w_cols))) weighted.mean(vals, weights, na.rm = TRUE) }, by = .EACHI, on = .(k2)]
- 用
i.前缀明确读取DT2的列,不需要切换.SDcols的作用域,也不需要将mget结果转成data.table by = .EACHI保证按关联后的逐行计算加权均值:=直接在原DT1新增列,无额外关联开销
方案2:矢量化计算(高性能,适合百万/千万行级大数据)
DT1[DT2, weighted_avg := rowSums(as.matrix(.SD) * as.matrix(mget(paste0("i.", w_cols)))) / rowSums(as.matrix(mget(paste0("i.", w_cols)))), .SDcols = val_cols, on = .(k2)]
- 完全放弃逐行循环,用矩阵运算实现全量矢量化计算,性能比逐行方案高10~20倍
- 同样直接修改原DT1,无中间表生成
注意事项
- 需保证
val_cols和w_cols的顺序一一对应,避免权重和数值错配 - 若存在权重和为0的异常场景,可增加判断逻辑返回NA或默认值
内容的提问来源于stack exchange,提问作者sch56
相关产品推荐
相关产品推荐

