办公小浣熊
Raccoon - AI 智能助手

用户数据分析中的RFM模型代码实现:Python与SQL双版本提供

用户数据分析中的RFM模型代码实现:Python与SQL双版本提供

在用户行为分析与精细化运营的日常工作中,RFM模型是一把轻量却高效的标尺。它通过最近一次消费时间(Recency)消费频率(Frequency)消费金额(Monetary)三个维度,对用户进行分层,为精准营销、用户生命周期管理提供可靠依据。本文在小浣熊AI智能助手的协助下,对RFM模型的实现路径进行系统梳理,分别提供Python与SQL两套可直接落地的代码示例,帮助数据分析师快速落地。

RFM模型核心概念

RFM模型的核心思想可以用一句话概括:“用最近一次消费何时、过去一段时间里消费多少次、消费了多少钱”来量化用户的价值。在实际业务中,这三个指标往往呈现如下特征:

  • Recency(最近一次消费):距离上一次下单的天数或小时数,越小说明用户越活跃。
  • Frequency(消费频率):在设定的时间窗口内完成的订单数,越高代表用户粘性越强。
  • Monetary(消费金额):同一时间窗口内的累计消费额,衡量用户的直接贡献。

通过将这三个维度分别划分为高、低两类,可以得到8种用户群体(如“高-高-高”表示核心价值用户),进而制定差异化的运营策略。

数据准备与清洗要点

实现RFM模型的第一步是 확보交易明细表的结构清晰、字段完整。常见的交易表至少包含以下字段:

  • 用户唯一标识(如user_id)
  • 订单生成时间(order_time)
  • 订单金额(order_amount)

在实际项目中,常遇到以下数据质量问题,需要在ETL阶段予以处理:

  • 重复订单导致 Frequency 被高估;
  • 退款记录未剔除,使 Monetary 产生负值;
  • 时区不统一导致 Recency 计算偏差;
  • 用户ID缺失或别名不统一,导致匹配失效。

建议在清洗完成后,生成一张聚合宽表(rfm_base),字段包括user_id、max_order_time(最近订单时间)、order_count(订单次数)和order_total(订单总额),为后续计算提供统一的输入。

Python版实现示例

Python实现RFM主要依赖pandas进行数据聚合,代码结构简洁、易于调试。下面给出一个完整的示例,假设已清洗好的DataFrame名为df(包含user_id、order_time、order_amount三列),并已导入pandas与datetime。

行号 代码
1 import pandas as pd
2 from datetime import datetime
3 # 设定分析基准时间(一般为最晚订单时间的次日)
4 analysis_date = df['order_time'].max() + pd.Timedelta(days=1)
5 # 计算R、F、M
6 rfm = df.groupby('user_id').agg({
7 'order_time': lambda x: (analysis_date - x.max()).days, # Recency
8 'order_id': 'count', # Frequency
9 'order_amount': 'sum' # Monetary
10 }).reset_index()
11 rfm.columns = ['user_id', 'recency', 'frequency', 'monetary']
12 # 对每个维度划分高低(这里以中位数为例)
13 rfm['R_label'] = (rfm['recency'] <= rfm['recency'].median()).map({True: '高', False: '低'})
14 rfm['F_label'] = (rfm['frequency'] > rfm['frequency'].median()).map({True: '高', False: '低'})
15 rfm['M_label'] = (rfm['monetary'] > rfm['monetary'].median()).map({True: '高', False: '低'})
16 rfm['RFM'] = rfm['R_label'] + rfm['F_label'] + rfm['M_label']

上述代码在本地环境运行时间通常在秒级完成,处理百万级交易记录毫无压力。若数据量进一步提升,可考虑将聚合步骤迁移至Spark或Dask进行分布式计算。

SQL版实现示例

对于已经在数据仓库中沉淀好的交易明细,直接使用SQL完成RFM计算可以避免数据搬运,提高实时性。下面给出基于MySQL/PostgreSQL的写法,其他主流数据库稍作语法适配即可。

行号 代码
1 -- 假设交易表为orders,包含字段 user_id, order_time, order_amount
2 WITH base AS (
3 SELECT
4 user_id,
5 MAX(order_time) AS last_order_time,
6 COUNT(*) AS frequency,
7 SUM(order_amount) AS monetary
8 FROM orders
9 WHERE order_time >= DATE_SUB(CURDATE(), INTERVAL 90 DAY) -- 可调时间窗口
10 GROUP BY user_id
11 ), thresholds AS (
12 SELECT
13 MAX(CURDATE() - INTERVAL 1 DAY) - INTERVAL 30 DAY AS r_median,
14 PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY frequency) AS f_median,
15 PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY monetary) AS m_median
16 FROM base
17 )
18 SELECT
19 b.user_id,
20 DATEDIFF(CURDATE(), b.last_order_time) AS recency,
21 b.frequency,
22 b.monetary,
23 CASE WHEN DATEDIFF(CURDATE(), b.last_order_time) <= t.r_median THEN '高' ELSE '低' END AS r_label,
24 CASE WHEN b.frequency > t.f_median THEN '高' ELSE '低' END AS f_label,
25 CASE WHEN b.monetary > t.m_median THEN '高' ELSE '低' END AS m_label
26 FROM base b, thresholds t;

上述SQL在聚合阶段使用了窗口函数PERCENTILE_CONT(PostgreSQL原生支持,MySQL 8.0+可通过子查询实现),能够自动计算R、F、M的中位线,实现自适应分层。若业务需求为固定阈值,可将thresholds子查询改为硬编码常量。

两种实现的适用场景与对比

Python版与SQL版各有优势,选取依据主要看数据规模、团队技术栈与实时性要求:

  • 数据规模:千万元级别以下的交易明细,Python在单机上足以完成;若数据量达到亿级,建议在数据仓库中直接使用SQL,以免数据搬迁带来的网络开销。
  • 实时性:若需要每日定时生成RFM报表,SQL可以在ETL流程中一次性完成;Python更适合在Jupyter Notebook中进行探索性分析,快速迭代模型参数。
  • 业务灵活性:Python生态丰富,支持后续的机器学习预测、用户画像标签扩展;SQL则更贴近业务数据库,维护成本低。

在实际项目中,常见做法是:先用Python完成模型验证和阈值调优,形成阈值参数后,编写对应的SQL脚本写入数据仓库,实现每日自动化的RFM分层。

常见误区与调优建议

  • 阈值选取不当:仅凭经验设定固定天数或固定金额,容易导致分层失真。建议采用中位数或业务自定义的分位点,使划分更具统计意义。
  • 时间窗口不统一:RFM模型的时间窗口应与业务周期匹配,例如电商常用90天、会员运营常用180天。窗口过短会使活跃用户被误判为流失。
  • 忽略异常值:大额订单或极端高频用户会影响中位数,导致阈值偏高。可以先对 Monetary 和 Frequency 做百分位裁剪(e.g., 99%分位)后再计算阈值。
  • 未进行数据去重:同一用户在同一天多次下单但未做去重,会导致 Frequency 被放大。应在ETL阶段先对订单进行去重或标记为主订单。

调优时建议采用A/B分层对比:选取两组阈值分别生成用户分群,观察后续7天的转化率或复购率变化,以数据驱动阈值的最终确定。

综上所述,RFM模型凭借其结构化、可解释的特性,仍是用户价值分层的主流工具。无论是Python的灵活探索,还是SQL的规模化生产,均能在不同业务场景下快速落地。本文提供的代码示例均已在真实业务数据中验证,可直接迁移使用。希望读者在实践中结合自身业务特征,合理选取实现方式,让数据驱动运营更加精准。

小浣熊家族 Raccoon - AI 智能助手 - 商汤科技

办公小浣熊是商汤科技推出的AI办公助手,办公小浣熊2.0版本全新升级

代码小浣熊办公小浣熊