RFM分析需先分位数离散化再规则映射,不可直接KMeans聚类;因量纲差异大、分布偏态、方向不一致,须对R取反后qcut分5级,F/M依分布自定义cut,再按R/F/M得分组合划分8类用户群。

RFM 分析在 Python 中完全可落地,但直接套用 sklearn 聚类会出错——RFM 三个维度量纲差异大、分布偏态严重,必须先做分位数离散化,而不是标准化后聚类。
为什么不能直接用 KMeans 对原始 RFM 数值聚类
用户最近购买时间(Recency)可能是 0–365 天,频次(Frequency)集中在 1–5 次,金额(Monetary)却可能从 10 元到 50000 元。KMeans 基于欧氏距离,Monetary 的量级会彻底淹没 Recency 和 Frequency 的区分度;而且电商数据中 Recency 是越小越好,Frequency 和 Monetary 是越大越好,方向不一致。
实操建议:
- 放弃对原始数值做
StandardScaler或MinMaxScaler - 改用分位数法(
qcut)将每个维度独立划为 5 级(1–5 分),高分代表高价值属性 -
Recency需先取负或倒排:用max(recency) - recency再分箱,确保“最近购买”得高分 - 分箱后拼成三位数 RFM 综合得分(如
543),再按规则映射到用户群(重要价值客户、一般发展客户等)
pd.qcut 分箱时的三个关键陷阱
电商订单数据常有大量 Frequency=1、Monetary 高度右偏,直接 qcut(..., q=5) 会报 ValueError: Bin edges must be unique。
立即学习“Python免费学习笔记(深入)”;
实操建议:
- 对
Frequency和Monetary,先用value_counts().head(20)检查是否集中于前几档;若 70% 用户Frequency==1,就别硬分 5 等份,改用pd.cut自定义区间(如[0,1,2,5,10,100]) -
Recency若含 0(当天购买),分箱前要加极小扰动(如+ 1e-6),避免qcut把所有 0 归为同一 bin 导致边缘 bin 样本过少 - 务必设
duplicates='drop'参数,否则重复边界值会触发异常
如何用规则映射代替聚类来定义用户群
RFM 本质是业务规则模型,不是统计模型。强行用 KMeans 得到的簇没有业务解释性,而基于分位数的 5×5×5=125 种组合,可通过简单规则压缩为 8 类典型用户群。
实操建议:
- 先计算每位用户的
R_score、F_score、M_score(均为 1–5 整数) - 定义核心判断逻辑:
— 若R_score >= 4 and F_score >= 4 and M_score >= 4→ 重要价值客户
— 若R_score → 一般保持客户(需唤醒)<br>— 若 <code>R_score = 4→ 重要发展客户(刚流失,高潜力) - 用
numpy.select或链式df.loc实现,比写多层 if 更快且可读
导出结果前必须检查的两个数据一致性点
分析结果一旦用于营销投放,错标一个“重要挽留客户”可能导致整批短信发给已注销用户。
实操建议:
- 核对
Recency计算基准日:必须统一用分析截止日(如2024-06-30),不能混用订单表最大日期或系统当前日期 - 确认
Monetary是否剔除了退款订单:必须 join 订单主表与退款明细表,把order_status == 'refunded'的行amount = 0,否则高价值用户会被虚高估计
真正卡住项目上线的,往往不是算法本身,而是 Recency 基准日和退款过滤这两处业务口径没对齐。


















