如何用tidyr高效实现分组内品类全组合匹配(大数据场景)
高效实现:按公司关联Shirts与Pants的所有商品组合
数据背景
现有一个包含company、product_type和product_ID三列的DataFrame,其中product_ID为全局唯一的商品ID。示例数据构造代码及输出如下:
input_example <- data.frame(company = c(rep("companyA", 4), rep("companyB", 6)), product_type = c(rep("shirts", 3), "pants", rep("shirts",4), rep("pants", 2)), product_ID = seq(1,10))
输出结果:
> input_example company product_type product_ID 1 companyA shirts 1 2 companyA shirts 2 3 companyA shirts 3 4 companyA pants 4 5 companyB shirts 5 6 companyB shirts 6 7 companyB shirts 7 8 companyB shirts 8 9 companyB pants 9 10 companyB pants 10
需求说明
获取每个company下shirts与pants的所有唯一组合,并关联对应的product_ID,期望输出如下:
> output company product_type.x product_ID.x product_type.y product_ID.y 1 companyA shirts 1 pants 4 2 companyA shirts 2 pants 4 3 companyA shirts 3 pants 4 4 companyB shirts 5 pants 9 5 companyB shirts 5 pants 10 6 companyB shirts 6 pants 9 7 companyB shirts 6 pants 10 8 companyB shirts 7 pants 9 9 companyB shirts 7 pants 10 10 companyB shirts 8 pants 9 11 companyB shirts 8 pants 10
当前方案问题
目前采用split结合inner_join的实现方式,在1亿行级别的业务数据下运行速度极慢,即使使用并行lapply也无明显改善:
output <- split(input_case, input_case$company) %>% lapply(., function(x){ x %>% inner_join(x, by=c("company")) %>% filter(product_type.x != product_type.y) }) %>% do.call(rbind,.) %>% filter(product_ID.x < product_ID.y) %>% remove_rownames()
基于tidyr/dplyr的高效实现方案
通过先筛选目标类型子集,再按公司做内连接的方式,避免全表自连接带来的冗余计算,大幅提升处理效率:
library(dplyr) library(tidyr) # 1. 分别筛选出shirts和pants的数据集,并重命名列名 shirts_data <- input_example %>% filter(product_type == "shirts") %>% rename(product_type.x = product_type, product_ID.x = product_ID) pants_data <- input_example %>% filter(product_type == "pants") %>% rename(product_type.y = product_type, product_ID.y = product_ID) # 2. 按company做内连接,直接得到所有shirts与pants的组合 output <- shirts_data %>% inner_join(pants_data, by = "company")
方案优势
- 减少冗余计算:仅处理需要的两类商品数据,避免了全表自连接产生的同类型商品无效组合,大幅降低中间数据量
- 向量化操作:基于dplyr的向量化处理逻辑,比循环/split的方式更适配大数据量场景
- 逻辑清晰:直接明确筛选目标类型后连接,代码可读性高,易于维护
如果业务数据中存在shirts的product_ID大于pants的情况,可在最后添加filter(product_ID.x < product_ID.y)来匹配需求中的ID顺序要求。
内容的提问来源于stack exchange,提问作者irene
相关产品推荐
相关产品推荐

