这节内容虽然排在某个数据分析系列教程的第二部分第十六节,但你把它单摘出来当成一篇独立的速查笔记也完全成立。关联规则分析,说穿了就是一件事:在大量交易记录里,找出那些“一起出现”得不同寻常的商品组合。很多人最早听说这个技术,都是因为那个啤酒与尿布的经典案例——超市发现买尿布的顾客常常顺手拿啤酒,于是把啤酒摆到尿布货架旁边,据说销量明显提升。这个故事今天已经很难考证真伪,但它背后的统计学思想值得认真掰一掰:到底凭什么判断两种商品“一起出现”是纯属巧合,还是真有内在关联?答案就是支持度、置信度、提升度这三个指标。
这篇文章我会从三个指标的原理讲起,解释它们各自解决了什么问题、如何计算,再用一组手工可验算的迷你数据完整走一遍,最后给出可以直接复用的Python代码。无论你是数据分析师、电商运营、产品经理,还是刚接触机器学习的新手,只要想把“谁和谁一起卖得好”这件事搞清楚,这篇文章都值得读完。
1. 购物篮分析到底在解决什么问题
1.1 两个真实业务场景
先抛两个场景,把需求讲透。
第一个是电商推荐。平台想做一个“买了A也看看B”的推荐位,核心问题是什么?不能只推热销品。如果一个商品本身销量极高,比如纸巾,它的出现概率天然就大,那么“买了牛奶也买纸巾”这种组合就没什么指导意义。平台真正关心的,是那些“本来以为不相关、实际却常常一起出现”的组合。这种需求下,光靠直觉不靠谱,必须用统计指标量化。
第二个是线下零售的陈列优化。超市想把货架摆得更有销售力,啤酒和尿布的故事就属于这一类。但线下场景有一个特点:单品数量成千上万,两两组合几十万种,三三组合上百万种,不可能靠人肉一个个看。这时候就需要一个自动化筛选框架:先定一个“最低出现次数”的门槛,把大量冷门组合滤掉,再在剩余组合里按可靠度排序。
两个场景的共同点是:都拿到了一张交易明细表,每行是一次购买记录,每行里的商品集合就叫“项集”;我们想从里面挖出形如“X -> Y”的规律,这个规律就叫关联规则。
1.2 关联规则的表达方式
关联规则的标准写法是 X -> Y,读作“买X的人会买Y”。这里X叫前件,Y叫后件,它们各自可以是一个或多个商品。比如“牛奶、面包 -> 黄油”,意思是买了牛奶和面包的顾客更容易顺手买黄油。
为什么这件事不能直接用“同时买的人数”来拍板?因为不同商品的基础销量差异巨大。热销商品和任何东西都容易一起出现,冷门商品再“忠诚”也显得数据很少。三个指标就是针对这个问题设计的:支持度负责衡量“这个组合有多普遍”,置信度负责衡量“这条规则有多可靠”,提升度负责衡量“这条规则到底有没有独特价值”。
打个比方:支持度是在海选演员——先看这个组合出场次数够不够多;置信度像是看专业水平——演技好不好;提升度则是看票房号召力——比起一个普通演员,这个演员是不是真能带动票房。三关全过,这条规则才算值得跟进。
2. 支持度:先筛掉那些“没人买”的组合
2.1 支持度公式与直觉理解
支持度的定义非常简单:规则X -> Y的支持度,等于同时包含X和Y的交易数,占总交易数的比例。写成公式就是:
Support(X -> Y) = 同时包含X和Y的交易数 / 总交易数
比如总共有1000笔订单,其中60笔既买了薯片又买了可乐,那么规则“薯片 -> 可乐”的支持度就是60 / 1000 = 6%。直观理解就是:任何一条规则,如果它连这个比例都撑不起来,说明这个组合在全部交易里只是极少数人的行为。组合太罕见,下一步怎么做决策都缺乏数据基础。
支持度还有一个身份:它是频繁项集的判定依据。只有当一个项集的支持度达到最小阈值,它才能进入后续分析。为什么先看支持度?因为它是“分母质量”的头道关卡。如果不管支持度,直接用置信度和提升度筛选数据,很容易被几个孤例误导。比如全店只有一个顾客同时买了天文望远镜和防寒服,置信度可能是100%,但总共只有一条交易,你总不能因为这个就把两件商品摆在一起吧。支持度就是用来把这种“小样本偶然”挡在门外的门槛。
2.2 最小支持度阈值怎么定才合理
支持度需要设置最小阈值,比如min_support = 5%。阈值怎么选,直接决定后续规则的数量和质量。
经验上,这个参数在不同场景差别很大:电商订单量大、品类多,如果商品普遍低频,5%可能太高,经常要调到1%甚至0.5%;线下零售在某一个品类内部做分析,比如只看啤酒这个细分货架,就可以把阈值抬高到10%以上。定阈值之前,最好先看一眼商品销量分布。我此前拿某电商脱敏数据做过实验,销量排名前20%的商品占据了80%的订单,这种“长尾数据”里,min_support设2%能得到比较平衡的规则集;如果整体商品都很集中,阈值可以明显往上提。
还有一个值得说明的性质:支持度具有单调递减特征。一个项集如果不够频繁,它的任何父级组合也不可能频繁;反过来,如果一个项集频繁,它的所有子集也一定频繁。这个性质叫Apriori性质,是所有高效关联规则算法的理论基石。它的实际价值在于:算法可以先把频繁项集找出来,只基于频繁项集生成规则,从而避免计算几百万个两两组合。
3. 置信度:买了A的人有多少会买B
3.1 从条件概率理解置信度
支持度衡量的是“整个交易库里,这个组合出现得多不多”;置信度衡量的则是“在买了X的人群里,有多少人同时买了Y”。换句话说,它是一个条件概率:
Confidence(X -> Y) = P(Y | X) = 同时包含X和Y的交易数 / 只包含X的交易数
这个公式看起来只比支持度多了一个“除以X的支持度”的操作,但意义完全不同。比如规则“薯片 -> 可乐”,假设同时买薯片和可乐的有60笔,买薯片的有80笔,那么置信度就是60 / 80 = 75%。含义是:在薯片消费者中,有四分之三的人会买可乐。这个数字直接反映了规则的可执行性——你打算给买薯片的人推荐可乐,有了这条规则,就知道推荐有75%的命中概率。
我习惯把置信度理解成“转介绍成功率”。一个老客户愿意把新客户介绍进来,说明两者之间有稳定关系;置信度就是在量化这个稳定关系。它解决了支持度“只问广度、不问深度”的问题:一个组合可能支持度不高,整体交易占比低,但在买了前件的消费者群体内部,后件的命中率其实很高。
3.2 为什么高置信度不等于强规则
这里必须停下来泼一盆冷水:置信度高,不能直接说明规则有价值。
原因在于,置信度只对比了“前件出现时后件出现的概率”,却没有对比“后件本身的整体出现概率”。举个例子:假设全店有40%的顾客买可乐。现在有一条规则“爆米花 -> 可乐”,买爆米花的人里有60%也买可乐。只看60%确实不低,但跟全店平均的40%对比一下就会发现,爆米花消费者买可乐的比例确实显著更高。可如果换一种环境:全店80%的人都会买可乐,这时“爆米花 -> 可乐”的置信度哪怕高达82%,也并不意味着爆米花和可乐之间有值得运营的强关联——因为大家本来就都在买可乐。
更极端的情况是,一个热销商品Y的支持度高达80%,那么任何以Y为后件的规则,置信度都有机会超过80%。这不一定代表X和Y有关系,可能只是大家本来就都在买Y。如果只按置信度排序,很容易导出一些“因为大家都在买可乐,所以随便推可乐就能命中”的凑数规则。这也是很多新人跑出一堆垃圾规则的主要原因。
所以业内有一条不成文的组合拳:先用支持度筛掉低频组合,再用置信度对剩余规则做初步排序,最后用提升度或杠杆率做最终筛选。三个指标是一套完整流程,少任何一个都会偏。
4. 提升度:一眼识破“假相关”
4.1 提升度公式与三种结果
提升度是三个指标里最值得琢磨的一个,公式是:
Lift(X -> Y) = P(Y | X) / P(Y) = Confidence(X -> Y) / Support(Y)
它其实就是在回答一个问题:有了X这个条件之后,Y发生的概率被人为拉升了多少倍?分子是“在X群体中Y的概率”,分母是“在全部人群中Y的概率”。两者一比,就能判断X和Y之间到底是正向拉动、负向抑制,还是纯粹各卖各的。
提升度的结果分三种情况:
- Lift > 1:正相关。买X会提升买Y的概率。比如买了爆米花的人购买可乐的概率是整体的1.5倍,那“爆米花 -> 可乐”就是一条值得配置的推荐规则。
- Lift = 1:X和Y相互独立。买不买X,对买Y没有任何影响。这种规则即使置信度再高,也只是“各自卖得好”的假象,业务价值很低。
- Lift < 1:负相关。买X反而降低了买Y的概率。负相关规则也有用——它提示了两类商品存在互斥关系,可以用在陈列隔离或优惠券发放策略上。
如果还要再打个比方,提升度衡量的是“介绍人的独特价值”。一个介绍人名下只有两个好友,但每次介绍都成功,成功率很高;可如果另一个普通人成功率也差不多,这个介绍人的价值就不大。提升度衡量的正是这个“比别人强多少”的增量。
4.2 后件基准概率:被忽视的关键变量
很多人第一次做关联分析时,用的是“支持度+置信度”组合,结果发现导出的规则大多荒诞不经,什么“纸巾 -> 牛奶”“登录页 -> 电商App”之类。为什么?就是少了提升度这一道关。
单独看支持度,它只告诉你某组合出现过多少次。单独看置信度,它只告诉你“前件发生时,后件发生的条件概率”。两个指标都忽略了后件的基准概率。如果后件本身在全店里就是高频商品,一条规则即使置信度很高,也可能是“搭了后件畅销的便车”。
举一个直观的例子。假设全店50%的人买面包,买牛奶的人里有70%也会买面包,那么“牛奶 -> 面包”的置信度是70%,提升度Lift = 0.7 / 0.5 = 1.4。这算是正向关联。可如果换一个比例:全店85%的人买面包,买牛奶的人里有80%也买面包,置信度还是80%,提升度却只有0.94。这时候你还觉得“牛奶和面包强相关”吗?事实是:面包是全店明星商品,大家结账时都会顺手拿,牛奶这个前件几乎没有提供额外信息。
提升度的价值就在这里:它把后件的“人口基数”也拉进了比较。只有当X的存在让Y的出现概率明显高于Y的全局概率时,我们才说这是真正的规律,而不是热销商品带来的幻觉。
5. 手工实战:7条交易数据算出三指标
5.1 迷你数据集与单商品支持度
理论讲再多,不如手算一遍记得牢。我这里构造了一个迷你数据集,一共7笔交易,每笔购买的商品如下:
T1: 牛奶、面包、鸡蛋 T2: 牛奶、面包 T3: 牛奶、鸡蛋 T4: 面包、奶酪 T5: 牛奶、面包、鸡蛋 T6: 面包、鸡蛋 T7: 牛奶、面包
先数四种商品的单商品支持度:
- 牛奶出现于T1、T2、T3、T5、T7,共5次,支持度5/7 = 71.4%
- 面包出现于T1、T2、T4、T5、T6、T7,共6次,支持度6/7 = 85.7%
- 鸡蛋出现于T1、T3、T5、T6,共4次,支持度4/7 = 57.1%
- 奶酪出现于T4,共1次,支持度1/7 = 14.3%
注意,奶酪只出现在一笔交易里,所以任何包含奶酪的二项组合,支持度都不可能超过14.3%。如果设置min_support = 40%,奶酪直接被淘汰出局。这就是支持度过滤低频组合的直观作用。
5.2 三条规则的完整计算过程
下面围绕牛奶、面包、鸡蛋这三个高频商品,分批计算规则指标。
先算规则“牛奶 -> 面包”:
- 同时包含牛奶和面包的交易:T1、T2、T5、T7,共4次,支持度 = 4/7 = 57.1%
- 置信度 = 4 / 5 = 80%,含义是买了牛奶的顾客中,有80%也买了面包
- 提升度 = 置信度 / 面包支持度 = 0.8 / (6/7) ≈ 0.933
再算规则“牛奶 -> 鸡蛋”:
- 同时包含牛奶和鸡蛋:T1、T3、T5,共3次,支持度 = 3/7 = 42.9%
- 置信度 = 3 / 5 = 60%
- 提升度 = 0.6 / (4/7) = 1.05
再算规则“面包 -> 鸡蛋”:
- 同时包含面包和鸡蛋:T1、T5、T6,共3次,支持度 = 3/7 = 42.9%
- 置信度 = 3 / 6 = 50%
- 提升度 = 0.5 / (4/7) = 0.875
最后算一下“面包 -> 牛奶”:
- 同时包含面包和牛奶:同样4次,支持度57.1%
- 置信度 = 4 / 6 = 66.7%
- 提升度 = 0.667 / (5/7) ≈ 0.933
把结果整理成表:
| 关联规则 | 支持度 | 置信度 | 提升度 |
|---|---|---|---|
| 牛奶 -> 面包 | 57.1% | 80.0% | 0.933 |
| 牛奶 -> 鸡蛋 | 42.9% | 60.0% | 1.05 |
| 面包 -> 鸡蛋 | 42.9% | 50.0% | 0.875 |
| 面包 -> 牛奶 | 57.1% | 66.7% | 0.933 |
这里有个现象值得注意:牛奶 -> 面包和面包 -> 牛奶的置信度并不相同,一个是80%,一个是66.7%,但提升度完全一致,都是0.933。原因在于提升度两边都做了“基准概率归一化”:前件换方向之后,分子分母对应变化,比值却保持不变。这也提醒我们,方向的选择对置信度影响明显,对提升度则不影响核心判断,落地时应该多结合业务逻辑来确定前件后件。
5.3 结果表揭示的三个重要信号
这张表藏着许多新手容易忽视的细节。
第一,规则“牛奶 -> 面包”的置信度高达80%,是全表最高。如果只看支持度和置信度,很多人会认为这是全店最值得推广的强规则。但提升度只有0.93,低于1,说明牛奶和面包不仅没有正向协同,反而呈现轻微的负相关。为什么会这样?回到原始数据:面包是全店出现率最高的商品,85.7%的顾客都会带上面包;而牛奶的购买者也几乎都会拿面包,但由于面包本身太普及,买牛奶并没有让买面包的概率再往上提,反而因为几笔“买了面包但没买牛奶”的交易,让比例略低于全局平均。这是典型的“热销商品之间的假关联”。
第二,真正有正向价值的是“牛奶 -> 鸡蛋”,提升度1.05,虽然只比1高了一点,但方向是对的:牛奶消费者中购买鸡蛋的比例是60%,高于全店平均的57.1%。做捆绑推荐时,优先选择这一条规则。
第三,“面包 -> 鸡蛋”提升度0.875,是负相关。买面包的人反而更少买鸡蛋。如果只看支持度42.9%,它和“牛奶 -> 鸡蛋”一样,看起来差别不大;但加上提升度之后,两条规则的业务导向完全相反。
这个手工案例想说明的要点是:单纯按置信度排序,你会挑中“牛奶 -> 面包”;加上提升度之后,你才会发现真正值得尝试的是“牛奶 -> 鸡蛋”。三指标一起看,排序逻辑完全不同。
6. Python快速实现:10行代码跑通关联分析
6.1 数据预处理:从交易表到one-hot矩阵
手算能建立概念直觉,工具才能处理几万行、几十万行真实交易数据。目前最常用的Python库是mlxtend,它封装了Apriori算法和规则生成函数,十来行代码就能完成一次关联分析。
开始之前,有一个预处理步骤容易踩坑:mlxtend要求输入是“每个商品一列”的one-hot矩阵,不是原始的“一行一笔交易、商品用逗号分隔”的宽表。所以要先用TransactionEncoder做一次编码转换。代码如下:
import pandas as pd from mlxtend.preprocessing import TransactionEncoder from mlxtend.frequent_patterns import apriori, association_rules dataset = [ ['牛奶', '面包', '鸡蛋'], ['牛奶', '面包'], ['牛奶', '鸡蛋'], ['面包', '奶酪'], ['牛奶', '面包', '鸡蛋'], ['面包', '鸡蛋'], ['牛奶', '面包'] ] te = TransactionEncoder() te_ary = te.fit(dataset).transform(dataset) df = pd.DataFrame(te_ary, columns=te.columns_) frequent_itemsets = apriori(df, min_support=0.4, use_colnames=True) print(frequent_itemsets)运行后,frequent_itemsets会输出每个频繁项集及其支持度,比如(牛奶、面包)的支持度0.571,(牛奶、鸡蛋)的支持度0.429。这里设min_support=0.4,是为了和上面手算的基准对齐,实际项目里要按数据量和业务目标调整。
6.2 Apriori算法与规则生成
频繁项集只是中间产物,下一步用association_rules函数生成规则。metric='lift'表示按提升度筛选,min_threshold=0.8表示只保留提升度不低于0.8的规则。
rules = association_rules(frequent_itemsets, metric='lift', min_threshold=0.8) result = rules[['antecedents', 'consequents', 'support', 'confidence', 'lift']] print(result)输出结果里,support列是规则支持度,也就是同时包含前件和后件的交易比例;confidence是置信度;lift是提升度。跑完之后,可以按lift从高到低排序,把正相关规则优先挑出来测试。
调参有三点经验值得记录:
- min_support太低,频繁项集爆炸,规则数量会多到无法逐条看;太高,又可能一条规则都出不来。建议先统计商品的平均出现频率,选一个略高于平均值的数作为初始阈值,再逐步微调。
- metric字段除了lift,还可以选confidence、support、conviction等。我的习惯是先用lift筛一遍,再在结果里按confidence排序,这样既保住“独特价值”,又保证命中率。
- use_colnames=True一定要加,否则输出的项集是列编号而不是商品名,排查起来相当痛苦。
6.3 实际调参经验分享
真实项目里,数据量动辄几十万行,一些细节会更早暴露出来。
第一,不要一次性对全量数据做关联分析。建议先用筛选条件缩窄范围,比如只分析某个月、某个门店或某个品类的订单。全量数据的噪音和稀疏程度会拖垮算法,而且生成的上万条规则根本看不过来。
第二,商品编码要统一。不同渠道导出的数据里,同一个商品可能有多个写法,比如“伊利纯牛奶”“纯牛奶250ml”“牛奶-纯”,不做清洗就分析,出来的规则会莫名拆散本来明显的关联。数据清洗环节在这个任务里至少占一半的工作量。
第三,如果只想快速验证一个组合是否成立,不必跑完整套Apriori。直接用透视表算出三种概率并手算提升度,反而更快,能减少很多不必要的数据工程成本。这在业务方只需要一次快速判断时非常管用。
7. 踩坑实录:关联规则实战问题速查
7.1 高频坑点与排查思路
关联规则看起来简单,实际做项目时坑可多了。挑几个我踩过的重点说说。
第一个坑是数据太稀疏。电商场景里,绝大多数商品的单笔出现率可能只有千分之一甚至更低。这时候如果执意用统一的最小支持度,你会发现频繁项集要么全是“爆款组合”,要么量大到爆炸。我的做法是先按品类拆分数据,或者引入加权思路,给核心商品更高的权重,避免小众优质关联被一刀切掉。
第二个坑是只跑算法、不看业务背景。算法输出“口红 -> 口红收纳盒”的强规则,逻辑上当然没问题,但如果运营团队根本不做这个方向的专题活动,这条规则对当下业务就是零价值。关联分析的最终产出不只是“有趣发现”,而是要能被业务直接用起来,否则分析报告就是自嗨。
第三个坑是混淆相关性与因果性。买某品牌咖啡的人更倾向于买某品牌燕麦奶,提升度很高,但这不意味着“买咖啡导致买燕麦奶”。真相很可能是两者都隶属于同一批注重健康生活方式的消费人群。提升度描述的是统计相关性,不是因果链条。把相关当因果去布置促销,轻则浪费预算,重则误导产品决策。
第四个坑是忽略负相关规则。多数人只会看提升度大于1的规则,但提升度小于1的负向规则同样有商业价值。比如某连锁门店的数据分析发现,买了高端预调酒的人,在同一个订单里几乎不会购买同品牌的高度白酒。这个负相关很有用:做套餐搭配时主动避开,做陈列时可以把两者隔开,免得互相抢占心智。
7.2 三个指标之外的进阶判断
三个指标本身已经构成一套完整筛选体系,但真正落地时,我建议再补充几个细节判断。
第一,规则的前件越长,业务落地越难。一条规则“牛奶、鸡蛋、面包 -> 黄油”可能提升度很高,但它的适用人群很窄,真正能触达的用户没几个。这类长前件规则适合做故事性的洞察,不适合做大规模的实时推荐。
第二,要关注规则两侧商品的价格带是否匹配。如果“高端咖啡豆 -> 高端保温杯”提升度很高,但两个商品分属不同价格带,盲目捆绑反而让顾客觉得强行搭配。这里需要结合客单价与毛利额来判断,而不是只看统计指标。
第三,如果交易数据带时间标签,可以做时序切片。夏季跑出来的规则和冬季很可能完全不同。我的习惯是分季节或分月份单独建模,而不是把整年数据揉成一团——否则很多季节性关联会被平均掉,最终策略变得不疼不痒。
第四,一定要设置最小置信度底线。提升度再高,如果置信度只有20%,意味着推荐命中率只有五分之一,用户体验会很差。行业里常见的底线是置信度不低于40%到50%,具体按业务容忍度调整。
做关联分析做得久了,最深的一个感受是:支持度、置信度、提升度三个指标,不是三个并列的过滤器,而是一条层层递进的筛选漏斗。先用支持度把低频噪音压下去,再用置信度确认规则在目标群体内部的稳定性,最后用提升度排除热销商品带来的假相关性。少一环,得到的就是一堆看起来漂亮、实际却用不起来的规则。
我个人有个小习惯:每次跑完Apriori后,都会把规则的提升度分布图画出来,重点看那些落在1.0附近的“边缘规则”。很多时候,比显著正相关更有业务嗅觉的发现,恰恰藏在这些模棱两可的边缘地带——它们不是统计上最强的规则,但往往是业务上最值得试的方向。希望这篇2.16节的笔记,能帮你把三个指标的内功彻底练扎实。