跨data.table查找求和过慢求助:2000万行数据性能优化
高效处理2000万行data.table的匹配求和方案
针对你2000万行的大数据量需求,循环或低效join肯定拖慢速度,这里给你两个基于data.table特性的高效方案,专门适配大规模数据场景:
方案一:向量索引法(速度最优,适合Cat.B为连续整数或可映射索引的场景)
如果DT.B$Cat.B是连续整数(比如示例里的1:100),这种方法完全避开join开销,直接用向量索引实现极速赋值:
library(data.table) set.seed(46) rows.DT <- 20e6 # 模拟实际数据量 DT.A <- data.table(Cat.A=1:rows.DT, Cat.B.1=sample(1:100, rows.DT, replace=TRUE), Cat.B.2=sample(1:100, rows.DT, replace=TRUE)) DT.B <- data.table(Cat.B=1:100, data.1=sample(1:10, 100, replace=TRUE)) # 提前按Cat.B排序提取data.1向量(Cat.B已连续有序可跳过) data1_vec <- DT.B[order(Cat.B), data.1] # 原地新增列并计算求和,全程无大表复制 DT.A[, `:=`( data_from_B1 = data1_vec[Cat.B.1], data_from_B2 = data1_vec[Cat.B.2], sum_data = data1_vec[Cat.B.1] + data1_vec[Cat.B.2] )]
如果Cat.B不是连续整数,改用命名向量索引,虽比整数索引稍慢,但仍远快于join:
# 生成以Cat.B为名称的向量 data1_named <- setNames(DT.B$data.1, DT.B$Cat.B) # 转字符型匹配命名后赋值 DT.A[, `:=`( data_from_B1 = data1_named[as.character(Cat.B.1)], data_from_B2 = data1_named[as.character(Cat.B.2)], sum_data = data1_named[as.character(Cat.B.1)] + data1_named[as.character(Cat.B.2)] )]
方案二:data.table高效左连接(适合Cat.B取值复杂的场景)
如果Cat.B取值分散、类型复杂,向量索引不便,就用data.table原生哈希join,速度远超base R的merge,且支持原地修改:
# 第一次左连接,匹配Cat.B.1并新增对应data.1列 DT.A[DT.B, on = .(Cat.B.1 = Cat.B), data_from_B1 := i.data.1] # 第二次左连接,匹配Cat.B.2并新增对应data.1列 DT.A[DT.B, on = .(Cat.B.2 = Cat.B), data_from_B2 := i.data.1] # 原地计算求和列 DT.A[, sum_data := data_from_B1 + data_from_B2]
关键注意事项
- 确保
DT.B$Cat.B无重复值,否则join会导致数据膨胀;若有重复,先聚合:DT.B <- DT.B[, .(data.1 = sum(data.1)), by = Cat.B] - 全程用
:=原地修改DT.A,避免创建新的大表,大幅节省内存 - 若DT.B有多列数据(如data.1、data.2),可一次性join多列:
DT.A[DT.B, on = .(Cat.B.1 = Cat.B), `:=`(data1_from_B1 = i.data.1, data2_from_B1 = i.data.2)]
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

