R语言:基于另一数据框行匹配筛选产品后求和val列
高效解决大数据框的条件求和问题
针对你这种大规模数据场景,绝对不要用循环——R的循环在处理海量数据时效率极低,我们可以用向量化的分组聚合+连接操作来搞定,下面给你两种常用的高效方案:
方案一:用dplyr(语法清晰易读)
先通过dplyr对dat1做预处理,提前计算每个(name, adress)组合下符合product条件的val总和,再和dat2做左连接,就能快速得到结果:
library(dplyr) # 定义你需要匹配的product向量 target_products <- c("prod1", "prod2") # 第一步:预处理dat1,计算符合条件的分组求和结果 summary_dat <- dat1 %>% filter(product %in% target_products) %>% # 筛选目标product group_by(name, adress) %>% # 按name和adress分组 summarise(total_val = sum(val), .groups = "drop") # 每组求和 # 第二步:和dat2左连接,自动补全无匹配的NA result <- dat2 %>% left_join(summary_dat, by = c("name", "adress")) %>% rename(val = total_val) # 重命名列到你想要的名字
运行后得到的result完全符合你的预期:
name adress val 1 Tom str2 2 2 Tom str3 5 3 Peter str1 4 4 Peter str2 NA
方案二:用data.table(大数据场景下速度更快)
如果你的数据量特别大(比如几十万甚至上百万行),data.table的性能会比dplyr更出色,写法也很简洁:
library(data.table) # 转换为data.table格式(这一步是data.table高效操作的前提) setDT(dat1) setDT(dat2) target_products <- c("prod1", "prod2") # 直接在dat1中筛选+分组求和,然后和dat2做左连接赋值 dat2[dat1[product %in% target_products, .(val = sum(val)), by = .(name, adress)], on = .(name, adress), val := i.val] # 此时dat2就是你要的结果 result <- dat2
为什么这两种方法比循环高效?
这两种方法都是向量化操作,R会把整个数据块作为整体处理,而不是像循环那样逐行遍历——后者在数据量变大时,会产生大量的内存开销和重复计算,速度会慢几个数量级。
内容的提问来源于stack exchange,提问作者WinterMensch
相关产品推荐
相关产品推荐

