别再只懂Apriori了!用Python手写一个超市购物篮分析,从牛奶面包数据里挖出隐藏的关联规则
从零实现购物篮分析用Python揭示牛奶与面包的隐藏关联超市货架上看似随机摆放的商品其实暗藏玄机。当顾客把牛奶和面包同时放进购物车时背后可能隐藏着值得挖掘的商业规律。本文将带你用Python从零实现经典的购物篮分析不依赖现成库彻底掌握关联规则挖掘的核心原理。1. 购物篮分析基础与数据准备购物篮分析Market Basket Analysis是零售行业最常用的数据分析技术之一它通过挖掘顾客购买商品之间的关联关系帮助商家优化商品陈列、制定促销策略。这种分析的核心在于发现如果顾客购买了A商品那么他们也倾向于购买B商品这样的规律。关键概念速览支持度Support规则A→B在所有交易中出现的频率置信度Confidence在包含A的交易中同时包含B的比例提升度Lift规则A→B的提升程度衡量相关性让我们从一个简单的数据集开始。假设我们收集了一家小型超市一周的购物数据包含五种商品牛奶、面包、苹果、香蕉和火腿。数据格式如下其中1表示购买0表示未购买1,1,0,0,0 # 购买了牛奶和面包 0,1,1,0,0 # 购买了面包和苹果 1,0,0,1,0 # 购买了牛奶和香蕉 0,0,1,1,0 # 购买了苹果和香蕉 1,1,0,0,1 # 购买了牛奶、面包和火腿使用NumPy加载这个数据集import numpy as np data np.loadtxt(shopping_data.txt, delimiter,) print(f数据集形状{data.shape}) # 输出(5,5)表示5笔交易5种商品2. 手动计算购买频率与共现次数理解购物篮分析的第一步是统计单个商品的购买频率和商品对的共现次数。这为我们后续计算支持度和置信度奠定基础。from collections import defaultdict # 初始化计数器 item_counts defaultdict(int) # 单个商品购买次数 pair_counts defaultdict(int) # 商品对共现次数 total_transactions len(data) # 总交易笔数 # 商品名称映射 items [milk, bread, apple, banana, ham] # 统计购买频率 for transaction in data: for item_idx, purchased in enumerate(transaction): if purchased: item_counts[item_idx] 1 # 统计商品对共现 for transaction in data: purchased_items [i for i, val in enumerate(transaction) if val] for i in range(len(purchased_items)): for j in range(i1, len(purchased_items)): pair (purchased_items[i], purchased_items[j]) pair_counts[pair] 1 # 同时记录反向组合 reverse_pair (purchased_items[j], purchased_items[i]) pair_counts[reverse_pair] 1 # 输出统计结果 print(商品购买次数统计) for item_idx, count in item_counts.items(): print(f{items[item_idx]}: {count}次)统计结果示例商品组合共现次数牛奶→面包2次面包→苹果1次牛奶→香蕉1次苹果→香蕉1次3. 实现支持度与置信度计算有了基础统计数据后我们可以计算关联规则的两个核心指标支持度和置信度。支持度计算公式支持度(A→B) 包含A和B的交易数 / 总交易数置信度计算公式置信度(A→B) 包含A和B的交易数 / 包含A的交易数Python实现代码# 计算所有可能的规则 rules [] for (premise, conclusion), count in pair_counts.items(): support count / total_transactions confidence count / item_counts[premise] rules.append({ rule: (premise, conclusion), support: support, confidence: confidence }) # 打印前5条规则 print(\n关联规则示例) for i, rule in enumerate(rules[:5]): prem, conc rule[rule] print(f规则{i1}: 如果购买{items[prem]}则也会购买{items[conc]}) print(f 支持度: {rule[support]:.2f}, 置信度: {rule[confidence]:.2f})注意支持度衡量规则的普遍性而置信度衡量规则的可靠性。两者都很重要但需要平衡考虑。4. 引入提升度优化规则质量单纯依赖支持度和置信度可能会产生误导。例如如果面包本身就很畅销那么牛奶→面包的置信度可能很高但这并不一定意味着两者有真正的关联。这时就需要引入提升度Lift。提升度计算公式提升度(A→B) 置信度(A→B) / 支持度(B)提升度解释1A和B正相关1A和B独立1A和B负相关Python实现# 计算提升度 for rule in rules: premise, conclusion rule[rule] support_conclusion item_counts[conclusion] / total_transactions rule[lift] rule[confidence] / support_conclusion # 按提升度排序 sorted_rules sorted(rules, keylambda x: x[lift], reverseTrue) print(\n按提升度排序的Top5规则) for i, rule in enumerate(sorted_rules[:5]): prem, conc rule[rule] print(f{i1}. {items[prem]} → {items[conc]}) print(f 支持度: {rule[support]:.2f}, 置信度: {rule[confidence]:.2f}, 提升度: {rule[lift]:.2f})典型提升度解读提升度1.5购买A的顾客购买B的可能性比普通顾客高50%提升度0.8购买A的顾客反而更少购买B5. 结果可视化与业务应用计算得到的规则需要直观展示才能发挥价值。我们可以使用matplotlib简单可视化import matplotlib.pyplot as plt # 提取Top5规则数据 top_rules sorted_rules[:5] premises [items[r[rule][0]] for r in top_rules] conclusions [items[r[rule][1]] for r in top_rules] lift_values [r[lift] for r in top_rules] # 创建条形图 plt.figure(figsize(10, 6)) bars plt.barh([f{p}→{c} for p,c in zip(premises, conclusions)], lift_values) plt.xlabel(提升度) plt.title(关联规则提升度Top5) plt.xlim(0, max(lift_values)*1.1) # 在条形上添加数值 for bar in bars: width bar.get_width() plt.text(width, bar.get_y() bar.get_height()/2, f{width:.2f}, haleft, vacenter) plt.tight_layout() plt.show()业务应用场景商品陈列优化将高提升度的商品组合摆放在相邻位置捆绑促销对关联性强的商品设计组合优惠个性化推荐根据顾客已选商品推荐相关商品库存管理关联商品保持同步进货和促销节奏6. 避免常见陷阱与误区在实际应用中购物篮分析有几个常见误区需要注意1. 忽视零交易的影响我们的示例数据很小现实中可能有数千种商品组合从未一起出现过。这些零同样包含重要信息。2. 过度依赖高置信度高置信度规则如果支持度很低可能只是偶然现象。比如鱼子酱→香槟置信度可能很高但实际交易数很少。3. 忽略商品层级关系不同品类、品牌的商品需要分层分析。将牛奶作为一个整体分析可能掩盖不同品牌间的差异。4. 不考虑时间因素季节性商品如圣诞树与装饰灯的关联可能只在特定时段成立。改进建议代码# 添加最小支持度阈值 min_support 0.1 filtered_rules [r for r in rules if r[support] min_support] # 添加最小提升度阈值 min_lift 1.2 filtered_rules [r for r in filtered_rules if r[lift] min_lift] print(f经过过滤后剩余{len(filtered_rules)}条有意义规则)7. 扩展思路与进阶技巧掌握了基础实现后可以考虑以下进阶方向1. 高效计算优化对于大规模数据可以使用位图等数据结构优化存储和计算# 将交易数据转换为位图表示 bitmap_data np.packbits(data.astype(bool), axis1) # 位运算快速计算共现 def bitwise_and_count(a, b): return np.count_nonzero(np.bitwise_and(a, b))2. 多层次关联分析除了商品间关联还可以分析商品类别关联购买时间关联早上vs晚上顾客属性关联年龄、性别等3. 实时分析架构对于线上商城可以设计实时关联规则推荐# 伪代码示例 def real_time_recommendation(cart_items, rules_db): recommendations set() for item in cart_items: related_items rules_db.get_related_items(item) recommendations.update(related_items) return recommendations - set(cart_items)4. 结合其他算法与协同过滤结合提高推荐精度使用图算法发现商品社区应用深度学习挖掘非线性关系