基于用户购买及交易历史的R语言商品推荐实现方法咨询
嘿,这个需求太贴合实际场景了——单纯的全局购物篮分析只能给所有人推一样的关联商品,结合用户维度才能做到真正的个性化推荐。我来给你拆解下在R里的具体实现步骤,分几个核心部分来走:
第一步:数据预处理(先把用户-交易-商品的关系理清楚)
首先你得确保数据包含三个核心维度:user_id(用户ID)、transaction_id(交易ID)、product(商品ID/名称)。先整个模拟数据给你参考,方便对应你的真实数据:
library(tidyverse) set.seed(123) # 固定随机种子,方便复现 # 模拟用户-交易-商品数据集 users_transactions <- tibble( user_id = rep(1:5, each = 3), # 5个用户,每个用户3笔交易 transaction_id = rep(1:15, each = 2), # 每笔交易买2件商品 product = sample(c("牛奶", "面包", "鸡蛋", "酸奶", "薯片", "可乐"), 30, replace = TRUE) )
接下来整理每个用户的历史购买集合,方便后续筛选用户未买过的商品:
# 提取每个用户的唯一购买商品列表 user_purchase_history <- users_transactions %>% group_by(user_id) %>% summarize(purchased_products = list(unique(product))) %>% ungroup()
第二步:两种核心实现思路
思路1:全局关联规则+用户历史过滤(高效通用)
先基于所有交易生成全局的商品关联规则,再针对每个用户,筛选出和他们历史购买商品关联度高、且从未买过的商品。这是最常用的方案,适合用户量较大的场景。
1.1 生成全局关联规则
用arules包完成经典的购物篮分析:
library(arules) # 把数据转成arules要求的transactions格式(按交易ID分组) transactions <- users_transactions %>% group_by(transaction_id) %>% summarize(items = list(product)) %>% pull(items) %>% as("transactions") # 生成关联规则(可根据你的数据调整supp/conf阈值) global_rules <- apriori( transactions, parameter = list(supp = 0.1, conf = 0.5, target = "rules") ) # 把规则转成数据框,方便后续处理 global_rules_df <- global_rules %>% as.data.frame() %>% mutate( lhs = as.character(lhs), rhs = as.character(rhs), # 提取规则前件的商品列表(去掉{}和分隔符) lhs_items = str_split(lhs, ", ") %>% map(~str_remove_all(., "\\{|\\}")) )
1.2 写个性化推荐函数
针对每个用户,过滤出符合条件的推荐商品:
get_personalized_recs <- function(target_user_id, user_history, rules_df, top_n = 3) { # 获取目标用户已购买的所有商品 user_purchased <- user_history %>% filter(user_id == target_user_id) %>% pull(purchased_products) %>% flatten_chr() # 筛选规则:前件是用户买过的商品子集,后件是用户没买过的商品 candidate_rules <- rules_df %>% filter(map_lgl(lhs_items, ~all(.x %in% user_purchased))) %>% filter(!rhs %in% user_purchased) %>% arrange(desc(lift)) %>% # 按lift排序(lift越高,商品关联度越强) distinct(rhs, .keep_all = TRUE) %>% # 去重同一商品的多条规则 head(top_n) # 返回结果,无合适推荐时返回提示 if (nrow(candidate_rules) == 0) { return("暂无个性化推荐,可查看店铺热门商品") } else { return(candidate_rules %>% select(rhs, lift, confidence) %>% rename(推荐商品 = rhs, 关联强度 = lift, 置信度 = confidence)) } } # 测试:给用户1推荐商品 get_personalized_recs(1, user_purchase_history, global_rules_df)
思路2:用户专属关联规则(更个性化,适合交易多的用户)
如果部分用户的交易记录足够多,可以针对单个用户的交易历史单独生成关联规则,推荐更贴合该用户习惯的商品。但要注意,用户交易少的话可能生成不出有效规则。
# 按用户分组生成专属关联规则 user_specific_rules <- users_transactions %>% group_by(user_id, transaction_id) %>% summarize(items = list(product)) %>% group_split(user_id) %>% # 按用户拆分数据集 map(~{ current_user_id <- .x$user_id[1] # 转成transactions格式 user_trans <- .x$items %>% as("transactions") # 生成用户专属规则(调低supp/conf阈值,因为单个用户交易少) rules <- apriori(user_trans, parameter = list(supp = 0.05, conf = 0.3, target = "rules")) if (length(rules) > 0) { rules %>% as.data.frame() %>% mutate(user_id = current_user_id) } else { # 无规则时返回空数据框 tibble(user_id = current_user_id, lhs = character(), rhs = character(), support = numeric(), confidence = numeric(), lift = numeric()) } }) %>% bind_rows() # 对应推荐函数 get_user_specific_recs <- function(target_user_id, user_history, user_rules_df, top_n = 3) { user_purchased <- user_history %>% filter(user_id == target_user_id) %>% pull(purchased_products) %>% flatten_chr() user_recs <- user_rules_df %>% filter(user_id == target_user_id) %>% filter(!rhs %in% user_purchased) %>% arrange(desc(lift)) %>% distinct(rhs, .keep_all = TRUE) %>% head(top_n) if (nrow(user_recs) == 0) { return("暂无专属推荐,可查看热门商品") } else { return(user_recs %>% select(rhs, lift, confidence) %>% rename(推荐商品 = rhs, 关联强度 = lift, 置信度 = confidence)) } } # 测试 get_user_specific_recs(1, user_purchase_history, user_specific_rules)
第三步:优化小技巧
- 冷启动处理:新用户没有交易历史时,可以推荐全局热门商品,或者基于用户属性(如年龄、性别)推荐同属性用户的热门商品
- 时间维度优化:只取用户最近3个月的交易历史,推荐更贴合当前需求的商品
- 类别过滤:加入商品类别信息,优先推荐同类别或互补类别的商品,避免完全不相关的推荐
- 性能优化:用户量很大时,优先用思路1(全局规则+过滤),思路2适合高活跃用户单独处理
内容的提问来源于stack exchange,提问作者Monty
相关产品推荐
相关产品推荐

