从Excel到Python:手把手教你用Pandas+Seaborn搞定手游RFM用户分群(附完整代码)
从Excel到Python:手把手教你用Pandas+Seaborn搞定手游RFM用户分群(附完整代码)
在手游运营的日常工作中,我们经常需要回答这样的问题:哪些玩家最有可能继续付费?哪些高价值玩家正在流失?如何针对不同类型的玩家制定差异化的运营策略?传统Excel虽然直观,但当数据量达到数十万行时,公式卡顿、图表刷新缓慢等问题就会接踵而至。本文将带你用Python的Pandas和Seaborn工具包,实现一套可复用的RFM分析流水线。
1. 理解手游场景下的RFM模型
RFM模型最早起源于传统零售行业,但在手游领域有三个关键差异点:
- 时间窗口更短:手游用户生命周期通常以周为单位计算,因此我们建议将R(最近一次付费)的时间跨度设置为7-14天
- 付费结构特殊:手游中存在"鲸鱼玩家"现象,TOP 5%的玩家可能贡献90%收入
- 行为数据丰富:除了付费记录,我们还能获取登录频次、关卡进度等辅助指标
# 典型的手游付费数据字段 raw_data.columns # ['player_id', 'payment_time', 'amount', 'item_id', 'server_id', 'vip_level']提示:在计算F(付费频次)时,建议先过滤掉小额付费(如6元首充),这些可能属于"试探性消费"
2. 数据准备与清洗实战
我们从游戏数据库中导出了最近90天的付费记录,原始数据包含37万条交易记录。首先需要处理几个典型问题:
常见数据质量问题及解决方案:
| 问题类型 | 检测方法 | 处理代码 |
|---|---|---|
| 测试账号 | VIP等级为999 | df = df[df.vip_level < 100] |
| 异常金额 | 3σ原则或百分位法 | q = df.amount.quantile(0.999) |
| 时间错误 | 未来时间戳 | df = df[df.payment_time <= pd.Timestamp.now()] |
# 数据清洗完整示例 def clean_payment_data(raw_df): # 去除测试账号 clean_df = raw_df[~raw_df['player_id'].str.startswith('test')] # 金额异常值处理(保留99.9%分位数以下) amount_upper = clean_df['amount'].quantile(0.999) clean_df = clean_df[clean_df['amount'] <= amount_upper] # 时间格式标准化 clean_df['payment_time'] = pd.to_datetime(clean_df['payment_time']) return clean_df3. 计算RFM指标的核心逻辑
不同于传统行业的等权处理,我们根据手游特性设计了加权算法:
def calculate_rfm(df, end_date): # 计算R值:最近一次付费距今的天数(倒序) rfm = df.groupby('player_id').agg( R=('payment_time', lambda x: (end_date - x.max()).days), F=('player_id', 'count'), # 付费次数 M=('amount', 'sum') # 付费总额 ) # 标准化处理(注意R值需要反向处理) rfm['R_score'] = 1 - (rfm['R'] - rfm['R'].min()) / (rfm['R'].max() - rfm['R'].min()) rfm['F_score'] = np.log1p(rfm['F']) # 对数变换处理偏态分布 rfm['M_score'] = np.log1p(rfm['M']) # 手游特化权重:R(50%) > F(30%) > M(20%) rfm['RFM_score'] = 0.5*rfm['R_score'] + 0.3*rfm['F_score'] + 0.2*rfm['M_score'] return rfm注意:对F和M取对数是为了降低"鲸鱼玩家"对整体分布的影响,使分群结果更具普适性
4. 可视化分析与业务解读
使用Seaborn可以快速生成专业级图表,这里推荐三种关键可视化:
4.1 相关性热力图
import seaborn as sns corr_matrix = rfm[['R_score', 'F_score', 'M_score']].corr() sns.heatmap(corr_matrix, annot=True, cmap='coolwarm')图示说明:在二次元卡牌游戏中,我们常发现R与F呈现负相关(近期付费频繁的玩家往往付费次数多)
4.2 RFM三维散点图
import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D fig = plt.figure(figsize=(10,8)) ax = fig.add_subplot(111, projection='3d') ax.scatter(rfm['R_score'], rfm['F_score'], rfm['M_score'], c=rfm['RFM_score'], cmap='viridis') ax.set_xlabel('Recency') ax.set_ylabel('Frequency') ax.set_zlabel('Monetary')4.3 分群箱线图对比
# 先定义分群规则 def segment_users(rfm_df): conditions = [ (rfm_df['RFM_score'] >= 0.8), (rfm_df['RFM_score'] >= 0.6) & (rfm_df['RFM_score'] < 0.8), (rfm_df['RFM_score'] >= 0.4) & (rfm_df['RFM_score'] < 0.6), (rfm_df['RFM_score'] < 0.4) ] labels = ['高价值', '潜力用户', '一般用户', '流失风险'] rfm_df['segment'] = np.select(conditions, labels) return rfm_df # 绘制分群对比 plt.figure(figsize=(12,6)) sns.boxplot(x='segment', y='RFM_score', data=rfm, order=labels)5. 运营策略落地建议
根据最终分群结果,我们可以制定针对性策略:
高价值玩家(Top 5%):
- 提供专属客服通道
- 提前体验新版本特权
- 定制化虚拟商品(如限定头像框)
潜力用户(Top 6-20%):
- 推送高性价比月卡
- 战斗数据周报(刺激竞争心理)
- 组队玩法邀请奖励
流失风险用户:
- 30天未登录触发召回邮件
- 回归礼包梯度设计(首日/三日/七日)
- 重要版本更新Push通知
# 生成运营名单示例 high_value = rfm[rfm['segment'] == '高价值'].index.tolist() print(f"需要重点维护的高价值玩家共{len(high_value)}人:") print(high_value[:5]) # 展示前5个ID在实际项目中,我们将这套分析流程封装成了Jupyter Notebook模板,新游戏上线后只需替换数据路径就能自动生成分群报告。相比原来用Excel手动处理的方式,现在完成全部分析只需15分钟,且能动态调整参数实时查看结果。
