如何用Tidyverse或Base R统计不同客户的产品组合出现次数
用Tidyverse或Base R统计客户产品组合的出现次数
这问题我刚好处理过类似的,用Tidyverse或者Base R都能轻松搞定,我给你详细拆解下实现步骤:
Tidyverse 实现方案
我先给你用Tidyverse的思路来做,核心是按客户分组生成所有符合长度要求的产品组合,再统一统计频次:
library(tidyverse) # 模拟你提供的原始数据 customer_data <- tibble( Customer = c(1,1,1,2,2,2,3,3,3,4,4), Product = c("A","B","C","D","E","F","A","B","D","A","B") ) # 核心处理流程 result_tidy <- customer_data %>% group_by(Customer) %>% # 对每个客户的产品生成所有长度≥2的组合,转成逗号分隔的字符串 summarise( product_groups = map(Product, ~combn(Product, seq(2, length(Product)), simplify = FALSE)) %>% flatten() %>% map_chr(~str_c(.x, collapse = ", ")) ) %>% # 展开所有组合,统计每个组合的出现次数 unnest(product_groups) %>% count(product_groups, name = "Number") %>% # 可选:按出现次数降序排序,方便查看高频组合 arrange(desc(Number)) print(result_tidy)
代码逻辑说明:
- 先按
Customer分组,确保每个客户的产品集合单独处理 - 对每个客户的产品列表,生成从2到产品总数的所有长度的组合(比如客户1有3个产品,就生成长度2和3的组合)
- 把嵌套的组合列表展开,再将每个组合向量转成逗号分隔的字符串格式
- 最后展开所有组合,用
count统计每个组合的出现次数,得到你需要的结果
Base R 实现方案
如果不想加载额外包,用Base R也能实现,思路和上面完全一致:
# 模拟原始数据 customer_data <- data.frame( Customer = c(1,1,1,2,2,2,3,3,3,4,4), Product = c("A","B","C","D","E","F","A","B","D","A","B") ) # 按客户拆分数据,得到每个客户对应的产品列表 customer_list <- split(customer_data$Product, customer_data$Customer) # 遍历每个客户的产品,生成所有长度≥2的组合并转成字符串 all_groups <- lapply(customer_list, function(products) { len_seq <- seq(2, length(products)) lapply(len_seq, function(n) { combn(products, n, FUN = function(x) paste(x, collapse = ", ")) }) %>% unlist() }) %>% unlist() # 统计组合频次并整理成目标数据框格式 result_base <- as.data.frame(table(all_groups)) colnames(result_base) <- c("Product Group", "Number") print(result_base)
代码逻辑说明:
- 用
split()把数据按客户拆分成列表,每个元素对应一个客户的产品向量 - 遍历每个客户的产品集合,用
combn生成所有符合长度要求的组合,转成字符串后合并成一个大向量 - 用
table()统计每个组合的出现次数,最后重命名列名得到和示例一致的格式
结果验证
不管用哪种方法,你都会得到和示例匹配的结果:
A, B出现3次(客户1、3、4的产品集合都包含这个组合)A, B, C、D, E, F、A, B, D各出现1次,分别对应客户1、2、3的完整产品组合
内容的提问来源于stack exchange,提问作者Mooks
相关产品推荐
相关产品推荐

