如何高效统计data.table条件合并后每个id1对应的唯一id2数量
高效替代方案:data.table非等值连接+分组聚合
直接用data.table的非等值连接配合分组聚合就能替代低效的逐行循环,百万级数据集也能高效处理,步骤如下:
核心代码
library(data.table) # 定义原始数据 table1 <- data.table(id1 = c(1324, 2324, 29, 29, 1010, 1010), type = c(1, 1, 2, 1, 1, 1), class = c("A", "A", "B", "D", "D", "A"), number = c(1, 98, 100, 100, 70, 70)) table2 <- data.table(id2 = c(1998, 1998, 2000, 2000, 2000, 2010, 2012, 2012), type = c(1, 1, 3, 1, 1, 5, 1, 1), class = c("D", "A", "D", "D", "A", "B", "A", "A"), min_number = c(34, 0, 20, 45, 5, 23, 1, 1), max_number = c(50, 100, 100, 100, 100, 9, 10, 100)) # 非等值连接+分组统计唯一id2数量 result <- table2[table1, on = .(type, class, min_number <= number, max_number >= number), allow.cartesian = TRUE][, .(nMatch = uniqueN(id2)), by = id1] print(result)
代码说明
- 非等值连接:通过
on = .(type, class, min_number <= number, max_number >= number)直接指定所有匹配条件,一次性完成所有行的匹配,替代逐行循环的查询操作。 - 分组聚合:连接完成后,按
id1分组,用uniqueN(id2)统计每个id1匹配到的唯一id2数量,得到目标nMatch字段。 allow.cartesian = TRUE:允许一个table1行匹配多个table2行的情况,避免因多匹配导致的报错,实际使用中如果确认不会出现极端多匹配场景,也可以省略。
效率优势
- 完全采用向量化操作,避免了逐行循环带来的大量函数调用和内存开销,data.table内部的索引优化和内存高效处理逻辑,能让百万级数据的处理速度比循环快几个数量级。
- 输出结果和你原来的循环方法完全一致:
id1 nMatch 1: 1324 2 2: 2324 3 3: 29 1 4: 1010 3
内容的提问来源于stack exchange,提问作者Adrian
相关产品推荐
相关产品推荐

