电商用户价值分群实战:用Pandas groupby+transform构建RFM模型
当你在电商平台浏览商品时,系统总能精准推荐你可能感兴趣的商品——这背后是数据科学家们通过用户行为分析构建的智能分群系统。本文将带你用Pandas的groupby和transform方法,从零开始构建一个电商用户价值分群模型。
1. 理解RFM模型与数据准备
RFM模型是衡量客户价值的经典方法,由三个核心指标组成:
- Recency(最近一次消费):用户最近一次购买距今的时间
- Frequency(消费频率):用户在一定周期内的购买次数
- Monetary(消费金额):用户在一定周期内的总消费金额
假设我们有一个电商平台的用户交易数据集:
import pandas as pd import numpy as np from datetime import datetime # 生成模拟数据 np.random.seed(42) user_ids = ['U'+str(i).zfill(4) for i in range(1, 1001)] dates = pd.date_range(end=datetime.today(), periods=365).to_list() categories = ['电子产品', '家居用品', '服装', '食品', '美妆'] data = pd.DataFrame({ 'user_id': np.random.choice(user_ids, 5000), 'order_date': np.random.choice(dates, 5000), 'amount': np.round(np.random.lognormal(mean=3, sigma=0.5, size=5000), 2), 'category': np.random.choice(categories, 5000) }) # 添加一些异常值 data.loc[np.random.choice(data.index, 50), 'amount'] *= 10数据预处理是分析的关键第一步:
# 检查数据质量 print(f"数据量: {len(data)}") print(f"缺失值统计:\n{data.isnull().sum()}") # 处理异常值 Q1 = data['amount'].quantile(0.25) Q3 = data['amount'].quantile(0.75) IQR = Q3 - Q1 data = data[~((data['amount'] < (Q1 - 1.5 * IQR)) | (data['amount'] > (Q3 + 1.5 * IQR)))] # 确保日期格式正确 data['order_date'] = pd.to_datetime(data['order_date'])2. 计算RFM基础指标
使用groupby和agg计算每个用户的RFM值:
# 设置分析基准日期 analysis_date = data['order_date'].max() + pd.Timedelta(days=1) # 计算RFM指标 rfm = data.groupby('user_id').agg({ 'order_date': lambda x: (analysis_date - x.max()).days, # Recency 'user_id': 'count', # Frequency 'amount': 'sum' # Monetary }).rename(columns={ 'order_date': 'recency', 'user_id': 'frequency', 'amount': 'monetary' }).reset_index() print(rfm.head())提示:在实际业务中,分析基准日期的选择很重要。如果是月度分析,通常使用当月最后一天作为基准。
RFM指标的统计分布:
| 指标 | 平均值 | 中位数 | 标准差 | 最小值 | 最大值 |
|---|---|---|---|---|---|
| Recency | 182.3 | 167 | 105.2 | 1 | 364 |
| Frequency | 4.5 | 3 | 3.8 | 1 | 27 |
| Monetary | 2456.7 | 1567.2 | 2834.1 | 32.5 | 28753.4 |
3. 使用transform进行RFM分箱
直接对原始数据表添加分箱标签:
# 定义分箱函数 def rfm_score(x, bins, labels): return pd.cut(x, bins=bins, labels=labels, include_lowest=True) # 对RFM进行5分制评分 rfm['r_score'] = rfm_score(rfm['recency'], bins=[0, 30, 90, 180, 365, float('inf')], labels=[5, 4, 3, 2, 1]) rfm['f_score'] = rfm_score(rfm['frequency'], bins=[1, 2, 3, 5, 8, float('inf')], labels=[1, 2, 3, 4, 5]) rfm['m_score'] = rfm_score(rfm['monetary'], bins=[0, 500, 1000, 2000, 5000, float('inf')], labels=[1, 2, 3, 4, 5]) # 计算RFM总分 rfm['rfm_score'] = rfm['r_score'].astype(int) + \ rfm['f_score'].astype(int) + \ rfm['m_score'].astype(int) # 将分箱结果合并回原始数据 data = data.merge(rfm[['user_id', 'r_score', 'f_score', 'm_score', 'rfm_score']], on='user_id', how='left')使用transform方法更高效地为每行数据添加分箱标签:
# 使用transform计算每行的用户分组指标 data['user_recency'] = data.groupby('user_id')['order_date'].transform( lambda x: (analysis_date - x.max()).days) data['user_frequency'] = data.groupby('user_id')['user_id'].transform('count') data['user_monetary'] = data.groupby('user_id')['amount'].transform('sum') # 直接应用分箱 data['r_score'] = rfm_score(data['user_recency'], bins=[0, 30, 90, 180, 365, float('inf')], labels=[5, 4, 3, 2, 1])4. 构建用户价值分群策略
基于RFM分数创建用户分群:
# 定义分群规则 def segment_user(row): if row['r_score'] >= 4 and row['f_score'] >= 4 and row['m_score'] >= 4: return '高价值用户' elif row['r_score'] >= 4 and (row['f_score'] >= 3 or row['m_score'] >= 3): return '潜力用户' elif row['r_score'] <= 2 and row['f_score'] >= 3 and row['m_score'] >= 3: return '流失风险用户' elif row['r_score'] <= 2 and (row['f_score'] <= 2 or row['m_score'] <= 2): return '流失用户' else: return '一般价值用户' # 应用分群 rfm['segment'] = rfm.apply(segment_user, axis=1) data['segment'] = data.apply(segment_user, axis=1) # 查看分群分布 segment_dist = rfm['segment'].value_counts(normalize=True).reset_index() segment_dist.columns = ['segment', 'percentage'] segment_dist['percentage'] = segment_dist['percentage'].apply(lambda x: f"{x:.1%}")用户分群分布示例:
| 用户分群 | 占比 | 特征描述 |
|---|---|---|
| 高价值用户 | 12.5% | 近期活跃、购买频繁、消费金额高 |
| 潜力用户 | 23.7% | 近期活跃,但消费频率或金额中等 |
| 流失风险用户 | 18.2% | 历史消费好但近期不活跃 |
| 流失用户 | 31.4% | 长期不活跃且历史消费一般 |
| 一般价值用户 | 14.2% | 各项指标处于中等水平 |
5. 分群结果分析与业务应用
不同用户群体的消费特征对比:
segment_analysis = rfm.groupby('segment').agg({ 'recency': 'mean', 'frequency': 'mean', 'monetary': 'mean', 'user_id': 'count' }).rename(columns={'user_id': 'count'}) segment_analysis = segment_analysis.sort_values('monetary', ascending=False)针对不同分群的运营策略建议:
高价值用户
- 提供专属VIP服务
- 提前推送新品和限量商品
- 给予更高的折扣和优惠
潜力用户
- 通过交叉销售提高客单价
- 推送相关品类商品提高购买频率
- 适度提供优惠券刺激消费
流失风险用户
- 发送召回邮件/短信
- 提供专属回归优惠
- 调研流失原因
流失用户
- 低成本触达保持联系
- 不投入过多营销资源
- 关注是否有自然回流
一般价值用户
- 常规营销活动覆盖
- 通过内容营销提升粘性
- 观察是否有升级潜力
6. 进阶:使用apply实现复杂分群
当业务规则更复杂时,可以使用apply方法:
def complex_segmentation(df): # 计算额外指标 df['avg_amount'] = df['monetary'] / df['frequency'] df['days_between_orders'] = 365 / df['frequency'] # 定义复杂规则 conditions = [ (df['recency'] <= 30) & (df['frequency'] >= 8) & (df['avg_amount'] >= 800), (df['recency'] <= 30) & (df['frequency'].between(4, 7)) & (df['avg_amount'] >= 500), (df['recency'] > 90) & (df['frequency'] >= 5) & (df['days_between_orders'] < 60), (df['recency'] > 180) & (df['frequency'] >= 3) ] choices = ['超级用户', '活跃用户', '沉睡优质用户', '普通沉睡用户'] df['complex_segment'] = np.select(conditions, choices, default='其他用户') return df rfm = rfm.groupby('user_id').apply(complex_segmentation)7. 结果可视化与报告输出
使用Matplotlib和Seaborn可视化分群结果:
import matplotlib.pyplot as plt import seaborn as sns plt.figure(figsize=(12, 6)) sns.scatterplot(data=rfm, x='recency', y='monetary', hue='segment', palette='viridis', alpha=0.6) plt.title('用户价值分群分布') plt.xlabel('最近消费天数') plt.ylabel('消费总金额') plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left') plt.tight_layout()生成业务报告摘要:
report = rfm.groupby('segment').agg({ 'user_id': 'count', 'recency': ['mean', 'std'], 'frequency': ['mean', 'std'], 'monetary': ['mean', 'std'] }).round(1) report.columns = ['_'.join(col).strip() for col in report.columns.values] report = report.reset_index().rename(columns={'user_id_count': '用户数'})在实际电商项目中,这种基于Pandas groupby和transform的用户分群方法,相比传统SQL实现有以下优势:
- 代码更简洁易维护
- 可以轻松添加复杂计算逻辑
- 便于与后续机器学习流程集成
- 支持交互式分析和快速迭代
通过将用户分群结果与推荐系统、营销自动化工具对接,企业可以实现真正的数据驱动运营。例如,对高价值用户展示高价商品,对流失风险用户推送优惠券,对不同分群采用差异化的沟通策略等。