基于 GoodsOrder.csv 与 GoodsTypes.csv, 严格复现书中 Apriori 案例的代码逻辑、参数设定和输出口径, 再从数据、方法、模型和决策表达四个维度做诊断与优化。
结论导向问题:哪些商品该相邻陈列?哪些组合值得捆绑?仅有规则表为什么还不够支撑经营决策?
分析路径:先复现关联规则建模流程,再从结果解释、方法改进和经营应用三个层面展开。
构建零售商品的 Apriori 关联规则模型,分析商品之间的关联性;再根据模型结果给出销售策略。
本次分析以既有零售案例为基础,先复现关联规则挖掘流程,再对结果进行诊断、优化与经营解释。
书页中写的是 9835 个购物篮、169 个商品、43367 条记录;当前项目下实际 CSV 是 9356 个购物篮、158 个商品、41080 条记录。
所以:代码逻辑可以完全复现,结果口径可以完全复现,但具体数值会跟着当前 CSV 版本变化。
这说明结果解读需要同时结合数据版本、参数设定与输出口径,不能孤立看待单张结果表。
查看数据特征、检查缺失、统计热销商品,并理解商品结构。
按 id 合并商品清单,转换为 Apriori 需要的事务列表格式。
找频繁项集,生成满足 min_support、min_conf、lift>1 的规则。
挑出重点规则,翻译成货架陈列、捆绑促销和补货建议。
if __name__ == '__main__':
dataSet = data_translation
L, supportData = apriori(dataSet, minSupport=0.02)
rule = gen_rule(L, supportData, minConf=0.35)
# 书中逻辑重点:
# 1. 先找频繁项集
# 2. 再从频繁项集生成强关联规则
# 3. 同时要求置信度达标、提升度大于 1
这一步做了三件事:读取 CSV、查看 info、按商品聚合销量。作用不是预测,而是先知道数据规模、字段结构和热销中心。
热销商品并不等于关联规则,但它能告诉我们:哪些商品是顾客最常买、最适合先做补货和显性陈列管理的中心商品。
书里先把商品销量表和类型映射表合并,再按 Types 聚合。这样商品级“长表”变成了可管理的品类结构。
这一步的价值是告诉业务:不是所有热销都在同一层级看。商品级适合补货,品类级适合陈列,品类内部适合做货架资源分配。
# 书中数据转换逻辑
data['Goods'] = data['Goods'].apply(lambda x: ',' + x)
data = data.groupby('id').sum().reset_index()
data['Goods'] = data['Goods'].apply(lambda x: [x[1:]])
data_list = list(data['Goods'])
data_translation = []
for i in data_list:
p = i[0].split(',')
data_translation.append(p)
# 作用:
# 一行一个商品 -> 一行一个购物篮 -> 每个购物篮是一个商品列表
Apriori 的输入不是“订单-商品明细长表”,而是“每个购物篮包含哪些商品”的事务型列表。转换完才能计算项集支持度。
# 书中规则生成逻辑
L, supportData = apriori(data_translation, minSupport=0.02)
rule = gen_rule(L, supportData, minConf=0.35)
# 在 calc_conf 中还要求:
if conf >= minConf and lift > 1:
ruleList.append((lhs, rhs, conf))
支持度保证规则“不是偶然”,置信度保证规则“有预测力”,lift>1 保证“这不是随机共现”。这三个约束一起,才让规则有业务意义。
按书中参数和代码逻辑运行,当前数据共得到 28 条 有效规则。代表性规则包括:
| lhs | rhs | support | confidence | lift |
|---|---|---|---|---|
| {其他蔬菜} | {全脂牛奶} | 0.078666 | 0.386758 | 1.439915 |
| {酸奶} | {全脂牛奶} | 0.058893 | 0.401603 | 1.495186 |
| {根茎类蔬菜} | {其他蔬菜} | 0.049808 | 0.434701 | 2.137187 |
买其他蔬菜的顾客,有 38.68% 同时买全脂牛奶。
买酸奶的顾客,有 40.16% 同时买全脂牛奶。
买根茎类蔬菜的顾客,有 44.87% 同时买全脂牛奶。
根茎类蔬菜与其他蔬菜之间的共购关系更强,lift 超过 2.13。
用 FP-Growth 替换 Apriori 的求解过程。在相同商品级阈值下,输出规则数量仍为 28,说明替换不改变结论,只优化实现方式。
把商品结果提升为经营语言:不再只说“酸奶买牛奶”,还说“饮料 + 果蔬会带动米粮调料、肉类和西点”。
品类级采用 support=0.15、confidence=0.55,把原本爆炸的 1269 条规则压缩为 28 条,便于汇报与决策。
# 优化后的两条路线 # 路线 A:商品级 FP-Growth(结果与书本对齐) goods_freq = fpgrowth(goods_matrix, min_support=0.02) goods_rules = association_rules(goods_freq, metric='confidence', min_threshold=0.35) # 路线 B:品类级 FP-Growth(表达更适合业务) type_freq = fpgrowth(type_matrix, min_support=0.15) type_rules = association_rules(type_freq, metric='confidence', min_threshold=0.55) type_rules = type_rules[type_rules['lift'] > 1]
它们分别解决了三个问题:运行方式更现代、结果层级更接近经营语言、输出数量更适合展示和筛选。
| 方案 | 支持度 | 置信度 | 频繁项集数 | 规则数 |
|---|---|---|---|---|
| 书本自写 Apriori | 0.02 | 0.35 | 129 | 28 |
| FP-Growth 商品级 | 0.02 | 0.35 | 129 | 28 |
| FP-Growth 品类级 | 0.15 | 0.55 | 29 | 28 |
| 规则 | 置信度 | lift |
|---|---|---|
| {果蔬;西点} ⇒ {肉类} | 58.09% | 1.56 |
| {果蔬;饮料} ⇒ {米粮调料} | 56.20% | 1.55 |
| {肉类;饮料} ⇒ {果蔬} | 67.80% | 1.48 |
这些规则比“某个单品带出某个单品”更适合直接翻译成区域陈列和组合促销方案。
如果目的是上课复现:书本自写 Apriori 是基线,必须保留。
如果目的是做经营建议:品类级 FP-Growth 更好,因为它能直接对应货架、区域、组合和促销动作。
全脂牛奶、酸奶、其他蔬菜相关规则最集中,应作为核心补货和重点陈列商品。
品类级规则表明顾客在这些品类之间存在稳定联动,可做家庭采购场景化摆放。
商品级用于捆绑推荐,品类级用于货架区位和促销主题,不要混用。
这组案例最值得带走的,不是“Apriori 会不会写”,而是:同一个算法结果,怎样组织成更能支撑业务决策的表达。