咱们先聊一个很实在的问题:你手里攒了一堆订单数据、用户行为数据,每天成千上万条记录摆在那里,直觉告诉你“这里面肯定有某种规律”,但真让你说具体是啥规律,你又说不出来。这时候就该上关联分析了。
我最早接触关联分析就是因为一个电商项目——运营天天追问“买A的人还喜欢买什么”,当时我用Python把Apriori算法跑起来,第一次看到频繁项集和关联规则从数据里自己“长”出来的时候,确实挺兴奋的。但兴奋劲儿过了之后才发现,真正的难点根本不是跑出规则,而是跑完之后那一大堆规则里,真正能落地到业务里的没几条。这也是我这篇文章想重点聊的东西:Python关联分析,从频繁项集到关联规则,到底哪些规则真正值得用。
这篇文章不准备把Apriori算法从头推导一遍,那些数学公式你自己翻书就能看到。我要讲的是实操层面:指标怎么选、参数怎么调、规则怎么筛、踩过哪些坑。适合刚接触关联分析的数据分析师,也适合想用Python做购物篮分析但还没找到门道的开发同学。文章会用到mlxtend这个库,它是目前Python生态里做关联分析最顺手的一个,没有之一。
1. 内容整体设计与思路拆解:别急着跑代码,先把业务问题翻译成算法问题
1.1 关联分析到底在解决什么业务问题
从业务角度看,关联分析解决的其实是三类问题。第一类是“同时出现”:用户购物车里同时放了哪些商品,对应的就是超市收银台前最常见的场景;第二类是“先后出现”:用户先做了A行为,隔多久做了B行为,比如先看详情页再下单,这类问题需要给数据加时间窗口,比单纯的同时出现要复杂一些;第三类是“组合推荐”:已经知道用户买了A,接下来最该推荐什么,这其实就是推荐系统里基于关联规则那一派的做法。
在动手写代码之前,我强烈建议你先想清楚自己的问题属于哪一类。因为不同类型对应的事务粒度完全不一样——“同时出现”你只需要把结算时间相同的商品凑成一条事务;“先后出现”就得自己定义一个时间窗口(比如24小时内),然后把窗口内的行为合并成一条事务。这一步不做对,后面算出来的所有指标都是错的。
我用过最笨也最有效的方法:拿到一份订单数据之后,先不看商品,先看订单结构。订单表里有几个字段、一行代表一条单品记录还是一条订单记录、同一笔订单里商品行数最多有多少、用户会不会一次买几十个相同SKU——这些东西决定了你后面怎么聚合数据。很多教程拿着现成的干净数据集讲算法,但真实业务里的数据永远是脏的,这一关必须自己过。
1.2 为什么用Python而不是直接上SQL或Excel
如果你处理的是百万行以上订单、要频繁调参跑不同组合,SQL能写出来但要写半天,Excel直接别想了;如果你要把它嵌入到推荐系统或数据管道里自动化跑,SQL更像是“算一次”,而Python天然适合“算一百次、每次换参数”。Python在这条链路里的优势是把整个流程打通了:pandas负责清洗和聚合,mlxtend负责跑频繁项集和规则,matplotlib负责输出可视化供汇报用,整套流程可以作为一个模块反复复用。
另外,Python社区里免费的实现和资料非常丰富,mlxtend就是开箱即用。它内部实现了Apriori和FP-Growth两种频繁项集挖掘算法,生成规则时还能指定按哪个指标排序,省去了自己写数据结构和循环的麻烦。说实话,Apriori算法本身并不复杂,核心就是“频繁项集的所有非空子集也必须是频繁的”这条先验性质,但自己从头实现一遍纯属重复造轮子,工作中直接用成熟库就行了。
1.3 整体流程:一条链路走通从数据到可用规则
我自己常用的流程固定是五步,这篇总结也按这个思路走:
- 数据准备:原始订单明细 → 一行一条事务的“购物篮”列表
- 事务编码:购物篮列表 → 布尔型的独热矩阵(True/False表格)
- 频繁项集挖掘:设定最小支持度、最大项集长度,跑Apriori或FP-Growth
- 规则生成:对每个频繁项集生成规则的前件和后件,按业务目标排序
- 规则筛选:用提升度、杠杆率、确信度多指标联合过滤,再结合业务语义圈出最终可用规则
这套流程看起来简单,但每一步都有需要注意的细节。比如第二步,很多人直接用TransactionEncoder转成独热矩阵,然后发现内存涨得离谱——那是因为他们没先做一层“商品聚合”,把同一笔订单里重复的商品先合并掉。再比如第三步,最小支持度定多少完全取决于数据规模,淘宝这种海量数据的场景你设0.1%可能都嫌高,而一个只有几千笔订单的小超市设0.5%可能就直接空手而归。这些经验下面逐一展开。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心指标拆解:支持度、置信度、提升度,以及它们为什么经常不够用
2.1 三个基础指标:各自解决的问题和局限
关联规则最基本的三个指标,相信你看过相关材料的话已经有印象。我用自己的话重新说一遍,重点在后半段——它们各自的局限。
支持度(Support):规则A→B的支持度是“同时包含A和B的事务数”除以“总事务数”。它衡量的是规则的覆盖面,值太低说明这条规则只发生在极少数交易中,参考意义有限。但到底多低算低,没有绝对标准,得看业务体量。我见过一个分析师把最小支持度设为0.1%,在几百万条数据上跑出了几千条规则,筛到最后留下的全是低频冷门商品组合,完全没法用。
置信度(Confidence):规则A→B的置信度是“同时包含A和B的事务数”除以“包含A的事务数”。它衡量的是“买了A的人有多大比例也买了B”,代表规则的可靠性。但这里有一个经典陷阱:如果B本身就是一个热门商品,不管有没有A,都有大量人买,那么无论A是啥,A→B的置信度都会虚高。比如B是“电池”,几乎人人都会买,那“任何商品→电池”的置信度都会在40%以上,你甚至能算出“安全套→电池”这种看着挺离谱但置信度不低的规则。
提升度(Lift):规则A→B的提升度是置信度 / (包含B的事务数 / 总事务数),也就是P(B|A) / P(B)。它衡量的是“A的出现是否让B的出现概率高于随机水平”。大于1是正相关,等于1是相互独立,小于1是负相关。理论上提升度越高规则越强,但实际使用中它也有坑——后面专门讲。
2.2 为什么单独看提升度会踩坑:一个最容易被忽略的问题
提升度看似照顾到了B的基础概率,但有一个问题:它没有惩罚低支持度。什么意思呢?假设你数据里有一笔交易,某用户同时买了“进口柠檬”和“手机支架”,只发生过这一次。此时“进口柠檬→手机支架”的支持度是1/10000=0.01%(如果总共1万笔订单),置信度竟然是100%(买柠檬的人全买了手机支架),提升度会非常高——因为手机支架整体购买率可能只有2%,100%除以2%就是50倍的提升度。
这种“一次都没卖出去几件,但只要卖出去就绑定另一个商品”的组合,提升度算出来极其诱人,实际却没有任何业务价值。做关联分析时,单看提升度你会筛出一堆稀奇古怪的规则,以为发现了什么不得了的高价值组合,实际上只是少数几次数据噪声。正确做法是支持度先行,先过滤掉低频组合,再看提升度是否显著高于1。
2.3 进阶指标:杠杆率(Leverage)、确信度(Conviction)、Kulczynski和失衡率
当你在实际项目里见过了前三个指标的各种翻车现场之后,就会开始寻找更robust的指标。mlxtend内置了不少,我实际用下来真正有区分度的是下面这几个:
-
杠杆率(Leverage):
P(A∩B) - P(A)P(B)。它衡量的是“A和B实际同时出现的概率减去假设二者独立时间时同时出现的概率”,直接以概率差的形式告诉你有多少人是因为关联而多买的那部分。相比提升度,杠杆率对支持度依然敏感,但它把“多少额外的交易”这个绝对量暴露了出来,做业务汇报时很直观。 -
确信度(Conviction):
P(A)P(¬B) / P(A∩¬B)。它的分子的含义是“A和B独立时A出现且B不出现的期望概率”,分母是“实际A出现且B不出现的概率”。如果B确实容易被A带起来,那“A出现但B不出现”的实际情况应该比独立假设下的期望更少,分母小,确信度就大。确信度是无限的,当A出现时B必然出现时为无穷大。这个指标的特点是对方向敏感,可以理解成“A对B的依赖有多强”。 -
Kulczynski(Kulc):
0.5 × (P(A|B) + P(B|A))。它取两个方向条件概率的平均值,消除了规则方向造成的不对称。比如买A的人大部分都买B,但买B的人很少买A,这种情况Kulc能更客观地反映A和B之间的真实关联强度,避免只看到高置信度方向的假象。 -
失衡率(Imbalance Ratio,IR):
|P(A|B) - P(B|A)| / (P(A|B) + P(B|A) - P(A∩B))。它衡量的是规则两个方向的失衡程度,值越接近0说明A和B之间的“双向往来”越均衡。当一个高提升度规则同时具有很高的失衡率时,基本可以断定这个规则是“单向绑定”——只有一边能推得动,反过来完全没戏。
这一堆指标如果一次全用上,会让决策过程变得复杂,所以我的习惯是分两级:先用支持度和杠杆率做粗筛,把低频噪声和无实际增量的规则剔除;再用提升度或确信度做精排,把候选规则里最“硬”的挑出来;最后用Kulc和IR做复核,排除方向失衡的伪规则。指标是工具,不是目的,回归业务逻辑才是王。
3. 实操过程与核心环节实现:用mlxtend从零跑通一条关联分析链路
3.1 环境准备:装库和Python环境检查
既然标题挂的是Python,那这一步还是得交代。建议在干净的虚拟环境里使用Python 3.8以上版本,一般不会遇到什么问题。需要安装的核心库是pandas、mlxtend和matplotlib(可选):
bash复制pip install pandas mlxtend matplotlib
如果你在装mlxtend时遇到网络慢或者下载失败,用国内镜像源可以省不少时间:
bash复制pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pandas mlxtend matplotlib
装完之后验证一下:
python复制import pandas as pd
from mlxtend.frequent_patterns import apriori, association_rules
from mlxtend.preprocessing import TransactionEncoder
print(pd.__version__)
能正常打印出版本号就说明环境没问题。这里多说一句,很多新手在vscode里配好了环境但跑代码时却报“找不到模块”,十有八九是当前解释器选错了。终端里which python看一眼,再到vscode右下角切换解释器,确保用的同一个环境。
3.2 数据准备:从订单明细到“一行一笔交易”的购物篮列表
我先模拟一份真实的订单数据。假设你是一家小超市的运营,拿到了当天的订单明细,大概长这样:
python复制import pandas as pd
orders = pd.DataFrame({
'order_id': [1001, 1001, 1001, 1002, 1002, 1003, 1003, 1003, 1003, 1004, 1004, 1005],
'item': ['牛奶', '面包', '鸡蛋', '面包', '牛奶', '牛奶', '鸡蛋', '薯片', '可乐', '面包', '薯片', '可乐']
})
print(orders.head())
注意同一条订单里商品是拆成多行的,这是绝大多数ERP和电商系统导出的原始形态。要做关联分析,第一步一定是把它聚合成“每行一条订单、每条订单以商品列表形式呈现”的结构:
python复制# 同一订单内重复商品去重
orders = orders.drop_duplicates()
# 按订单聚合为商品列表
basket = orders.groupby('order_id')['item'].apply(list).tolist()
print(basket)
# 输出示例:[['牛奶', '面包', '鸡蛋'], ['面包', '牛奶'], ['牛奶', '鸡蛋', '薯片', '可乐'], ['面包', '薯片'], ['可乐']]
这里drop_duplicates()很重要。一笔订单里买了3瓶可乐,在“是否购买”这个维度上它和买1瓶可乐没有区别,都是“买了”。如果不先去重,后面转独热矩阵时会报奇怪的数据错误。
3.3 事务编码与频繁项集挖掘:TransactionEncoder和apriori的用法
有了购物篮列表之后,下一步用TransactionEncoder把它转成一个布尔型的DataFrame,每个商品占一列,买了为True,没买为False:
python复制from mlxtend.preprocessing import TransactionEncoder
import pandas as pd
te = TransactionEncoder()
te_ary = te.fit(basket).transform(basket)
df = pd.DataFrame(te_ary, columns=te.columns_)
print(df)
这一步出来的表格就是关联分析的输入。每一行是一笔订单,每一列是一个商品,True/False表示该订单是否包含该商品。稀疏矩阵比较大时会很吃内存,但一般小规模数据完全没问题。
接着跑频繁项集:
python复制from mlxtend.frequent_patterns import apriori
frequent_itemsets = apriori(
df,
min_support=0.2, # 最小支持度,我的经验先设为总订单数的2%~5%再调
max_len=3, # 限制最大项集长度,避免组合爆炸
use_colnames=True # 返回商品名称而不是列索引
)
frequent_itemsets.sort_values('support', ascending=False)
输出里每一项会多一列itemsets,里面是一个frozenset,表示哪些商品组合在一起。这里要给新手提个醒:min_support设得太小(比如0.001)而商品种类又多时,Apriori会产生海量项集,轻则跑得很慢,重则直接把内存打爆。最稳的办法是先跑一版大的支持度(比如0.1)看看分布,再逐步调小,而不是一上来就给个极小值。
3.4 规则生成:到底按哪个指标排序,直接决定你看到什么
频繁项集算出来后,用association_rules生成规则。这一步是重头戏,因为同一个频繁项集可以拆出很多条规则,而按不同指标排序会得到完全不同的候选列表。
python复制from mlxtend.frequent_patterns import association_rules
rules = association_rules(
frequent_itemsets,
metric='lift', # 也可以换成 'confidence' / 'leverage' / 'conviction'
min_threshold=1.2, # 阈值
)
rules = rules[['antecedents', 'consequents', 'antecedent support',
'consequent support', 'support', 'confidence', 'lift',
'leverage', 'conviction']]
rules.sort_values('lift', ascending=False)
这里有个非常容易踩坑的地方:association_rules默认只用support和confidence做筛选,但你在metric里指定lift之后,它会筛选出lift≥1.2的规则。注意,它不会帮你检查支持度够不够,你需要在前面调好min_support,否则很多低支持度高提升度的“噪声规则”也会混进来。
我在一个真实项目里遇到过这样的情况:跑完规则后,按提升度排序,排在最前面的竟然是“修正带→宠物零食”,提升度高达28,但支持度只有0.4%。因为这两个商品的购买频次都很低,只要有一两笔订单同时包含它们,提升度就会虚高到吓人。后来我在规则生成之后又做了一道过滤,把支持度小于1.5%的规则全部剔除,再往下看,剩下的规则才真正符合业务直觉。
3.5 结果展示与可视化:快速向业务方证明这套方法靠谱
规则算出来了,接下来多数人的需求是“怎么展示给不写代码的人看”。matplotlib的散点图是很好的方式,横轴是支持度,纵轴是提升度,颜色深浅表示置信度,一眼就能看出哪些规则又普遍又强:
python复制import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 解决中文乱码
plt.rcParams['axes.unicode_minus'] = False
rules['support'].values
plt.figure(figsize=(10, 6))
sc = plt.scatter(
rules['support'],
rules['lift'],
c=rules['confidence'],
cmap='viridis',
s=20 + rules['support'] * 500 # 点的大小也映射支持度,越大代表覆盖范围越广
)
plt.colorbar(sc, label='confidence')
plt.xlabel('support')
plt.ylabel('lift')
plt.title('关联规则分布(支持度 vs 提升度)')
plt.show()
这种图通常能明显看到右上方的少数高亮“明星规则”——它们同时具备高覆盖(支持度高)和强关联(提升度高),正是业务上最值得关注的候选。筛选时我习惯先右键点住图右上角的那些点,看它们是哪些规则,再回到表里精查。
4. 规则筛选与业务落地:哪些规则真正值得用,怎么用
4.1 一套可复用的“三步筛选法”
代码跑通只是第一步,真正的功夫在筛选。我总结了一套三步走的筛选策略,后面每个项目基本套用:
第一步,用支持度和杠杆率把“噪声”抠掉。给支持度设一个底限,我通常拿总订单数的1%~2%做参考,体量小就低一些,体量大多就高一些。支持度太低的规则,哪怕指标再漂亮也只能算随机巧合。再看杠杆率,杠杆率至少得是正数——如果实际共同出现的概率都比独立假设时低了,说明这俩商品之间压根没有正向关联,是负相关,直接排除。
第二步,用提升度或确信度找出“真正的强关联”。提升度大于1.5或者确信度大于1.3的规则,才值得进入候选池。这里我建议优先用确信度,它比提升度稳定,而且能表达“A出现时B几乎一定出现”这种强绑定关系。项目中我会把确信度大于1.8的规则单独拉出来看一遍,这里面经常能发现高价值的组合。
第三步,人工复核业务语义。这一步机器替代不了。同品类商品(比如“苹果”和“香蕉”)产生高关联是废话;“牛奶”和“麦片”的关联,要么是真的组合促销有效,要么是大家都放在同一个货架上,运营怎么看都合理。真正的生意藏在跨品类规则里——“啤酒”和“纸尿布”这种经典组合。凡是连业务方自己看了都莫名其妙的高指标规则,大概率是数据噪声,别犹豫,直接删。
4.2 几个典型的“高指标低价值”规则案例
我整理几个曾经在实战中遇到过的经典场景,你可以对照着检查:
| 规则形态 | 指标表现 | 实际业务价值 | 原因分析 |
|---|---|---|---|
| 冷门商品A→爆款商品B | 提升度很高,支持度极低 | 无价值 | 冷门商品只出现过一两次,无条件概率估算失真 |
| 竞品A→竞品B | 置信度高,提升度≈1 | 无价值 | B本身售出概率高,置信度假性高,提升度说明无增量 |
| 套装商品A→套装内商品B | 各类指标都很高 | 价值有限 | 组合原本就是强制绑定销售的,不需要推荐算法再发现 |
| 节日性组合(春联→窗花) | 季节性显著提升 | 特定节点有用 | 只在春节前有意义,平时推反而打扰用户 |
看完这张表你可能会明白,单纯靠算法指标给规则分级是远远不够的。好的分析师会把指标当成“嫌疑犯名单”,再从里面挨个审人,最终落地的规则必须过业务逻辑这一关。
4.3 结合业务场景:对目标商品做定向分析而不是全量跑批
当你准备把关联分析嵌入到生产环境时,我强烈建议你别一遍又一遍做全量规则挖掘——开销大、噪声多,而且产出不聚焦。更高效的做法是“定向分析”:业务方告诉你重点推哪个商品(比如新品要搭着老品卖),你只需挖掘包含该商品的所有频繁项集和规则。
在代码层面怎么实现?最简单的办法是在算完频繁项集之后过滤一遍,只保留包含目标商品的项集:
python复制target_item = '牛奶'
focused_itemsets = frequent_itemsets[
frequent_itemsets['itemsets'].apply(lambda x: target_item in x)
]
focused_rules = association_rules(focused_itemsets, metric='lift', min_threshold=1.0)
这样跑出来的规则全都围绕“牛奶”展开,方便运营直接做捆绑策略:“牛奶→面包”提升度是多少、“牛奶→麦片”置信度是多少,清清楚楚。而且计算量小很多,规则数量也少很多,不用在一堆不相关的组合里大海捞针。
4.4 当数据量变大时:从Apriori切到FP-Growth的时机与方法
如果你的订单量膨胀到了几百万行,而且商品种类有上万种,Apriori反复扫描数据集的瓶颈会变得非常明显。此时mlxtend还提供了FP-Growth算法,它的关键在于只需要两次扫描数据库,并借用FP树结构压缩数据,避免像Apriori那样反复生成候选集。
切换的成本几乎为零,只要把导入改成from mlxtend.frequent_patterns import fpgrowth,后面参数用法一模一样:
python复制from mlxtend.frequent_patterns import fpgrowth
frequent_itemsets_fp = fpgrowth(
df,
min_support=0.01,
max_len=3,
use_colnames=True
)
我在一次处理约80万笔订单时做过对比,同样的min_support下,Apriori跑了20多分钟,FP-Growth大概3分钟内出结果。这种情况下没有理由不换FP-Growth。但在数据量不大(十万级以下)时,两者差别不明显,用你熟悉的那个就行。
4.5 从规则到推荐:怎么把规则套进推荐逻辑里
最后聊一下怎么把筛选出来的规则真正用到线上。最常见的做法是把它做成一个“关联推荐词表”:对每个频繁前件(如“牛奶+面包”)存下对应的最优后件(按提升度排序取Top3),线上用户购物车里有“牛奶+面包”时,直接查表推荐“鸡蛋”或“麦片”。这个方案实施简单、延迟低,还能解释来源(“买过牛奶和面包的人还买了鸡蛋”),比纯协同过滤的黑盒推荐更有说服力。
实现上就是把规则转换成一个字典映射:
python复制# 基于筛选好的rules,构造前件->后件推荐映射
rec_dict = {}
for _, row in rules.iterrows():
antecedent = tuple(sorted(row['antecedents']))
consequent = tuple(sorted(row['consequents']))
lift_val = row['lift']
if antecedent not in rec_dict:
rec_dict[antecedent] = []
rec_dict[antecedent].append((consequent, lift_val))
# 取每个前件提升度最高的5个候选后件
for key in rec_dict:
rec_dict[key].sort(key=lambda x: x[1], reverse=True)
rec_dict[key] = rec_dict[key][:5]
真实工程落地时,这个映射表可以预计算存到Redis里,线上直接按键取值,毫秒级响应。
5. 常见问题与排查技巧实录:看完少走至少一半弯路
5.1 运行时报错/结果异常的排查清单
我在多个项目里反复踩过下面这些坑,整理成一张速查表,你一旦遇到同类问题可以照方抓药:
| 症状 | 可能原因 | 解决方法 |
|---|---|---|
ValueError: The truth value of a DataFrame is ambiguous |
传入association_rules的frequent_itemsets格式不正确,或DataFrame有重复列名 |
检查频繁项集的列名,确保是support和itemsets |
| 跑Apriori时内存暴涨 | min_support设太低,候选集数量爆炸 |
逐步调高min_support;限制max_len;或用fpgrowth替代 |
| 规则数量巨大,完全看不过来 | min_threshold太低,或没有做二次过滤 |
提高metric阈值,增加支持度和杠杆率下限;按目标商品定向分析 |
| 提升度极高但业务方不认 | 低支持度高噪声规则混入 | 先按支持度/杠杆率过滤,再按提升度排序 |
| 中文商品名在结果里变成乱码 | 控制台编码问题或matplotlib字体问题 | 终端设UTF-8,绘图用rcParams配置中文字体 |
| 同一商品在不同订单中名字不一致 | 数据脏:如“鲜牛奶”和“鲜牛奶(250ml)” | 聚合前先做商品名标准化,否则会被当成两个商品 |
5.2 实战中最容易忽略的三件事
第一件:最小支持度的设定不能拍脑袋。 我见过最离谱的做法是网上抄一个0.05就往上套,结果跑出来的规则要么为零要么爆炸。正确做法是先从数据里看一下单个商品的支持度分布:如果你的数据里有80%的商品只出现在不到1%的订单里,那么最小支持度就不能设太高,否则根本挖掘不到这些长尾商品之间的组合。可以用一行代码快速检查:
python复制item_support = df.mean().sort_values(ascending=False)
print(item_support.describe())
看完分布之后,我会把min_support设在“中位数商品的购买率”附近,再上下调整两三版对比结果,而不是一上来就固定死。
第二件:频繁项集不是越多越好,规则也不是越强越好。 一个健康的关联分析结果,应该是你能在半小时内把Top规则全部过一遍,并且每条都能用业务逻辑解释。如果筛选完还有上千条,说明你过滤太松;如果只剩两三条,可能过滤太狠了,需要放宽一点。调参的过程本质上是在覆盖率和精准度之间找平衡,没有唯一正确答案。
第三件:别把相关性当因果。 即使“啤酒→纸尿布”的提升度很高,也未必意味着“啤酒导致了纸尿布购买”。它可能只是说明买这两种东西的人群画像重叠度高——都是周末带娃的年轻爸爸。这个区别非常重要,因为如果你把它当因果链去设计“买啤酒送纸尿布券”的促销活动,很可能达不到预期的效果。关联规则给的是“同时出现的模式”,具体怎么用、用到什么程度,是业务问题。
5.3 对“哪些规则真正值得用”的最终判断标准
在这一篇里反复绕不开的核心问题就是标题里那句“哪些规则真正值得用”。我个人的判断标准大致有四条,你可以拿着往任何候选规则上套:
- 支持度是否过了底线?没过就是噪声。
- 提升度或确信度是否显著大于1?不够就是废话。
- 业务上是否说得通?说不通就要怀疑数据和逻辑。
- 能不能直接形成动作?“给买牛奶的人推荐面包”比“给买牛奶的人推送牛奶促销”更像一个可执行的动作。
满足这四条,基本可以判断是一条值得用的规则。不满足任何一条的,哪怕指标再漂亮,我都建议直接丢掉——做分析的人要敢于给自己做减法。
5.4 最后一个经验之谈:把分析工具沉淀成可复用的脚本
文章快收尾了,分享一个让我后期效率明显提升的习惯:不要把关联分析的流程散落在一个个临时ipynb里,而是把它封装成一个函数,定义好参数,以后换数据直接调用。
python复制def run_association_analysis(
orders_df,
id_col='order_id',
item_col='item',
min_support=0.02,
max_len=3,
metric='lift',
min_threshold=1.2,
target_item=None
):
# 1. 聚合去重
basket = orders_df.drop_duplicates().groupby(id_col)[item_col].apply(list).tolist()
# 2. 编码
te = TransactionEncoder()
df = pd.DataFrame(te.fit(basket).transform(basket), columns=te.columns_)
# 3. 频繁项集
if df.shape[1] > 0:
itemsets = apriori(df, min_support=min_support, max_len=max_len, use_colnames=True)
else:
return None, None
# 4. 目标商品定向过滤
if target_item:
itemsets = itemsets[itemsets['itemsets'].apply(lambda x: target_item in x)]
# 5. 规则生成
if len(itemsets) == 0:
return itemsets, None
rules = association_rules(itemsets, metric=metric, min_threshold=min_threshold)
return itemsets, rules
这样封装之后,遇到新的订单数据我只需要一行代码就能跑出结果,省下的时间都用来干更有价值的事——和业务方聊组合策略、核算促销效果。
关联分析这套东西,算法层面并不难,真正见功力的是指标选择、参数调优和业务翻译。拿到一份数据,先想清楚要解决什么问题,再动手跑代码,最后按下表复盘一遍哪些规则值得用、哪些是噪声。按这个路子走下来,Python关联分析在你手上就不再是教程里的demo,而是能实打实产生业务价值的生产力工具。
