电商用户行为分析实战:Python+Pandas实现RFM分层与转化漏斗

电商用户行为分析实战:Python+Pandas实现RFM分层与转化漏斗 简介电商用户行为分析是一份面向大数据分析方向毕业设计或相关课题研究的可运行源码包围绕2017年11月25日至12月3日淘宝用户超1亿条行为记录梳理了数据导入、清洗、异常值处理、Hive分析及可视化全流程重点呈现用户流量、行为转化率、行为习惯、RFM高价值用户识别和商品维度分析等内容。包内共20个文件压缩包约16.37MB以Python脚本、JSON结果、Markdown说明文档为主同时包含CSV样例数据和Shell安装脚本便于快速搭建运行环境、理解分析逻辑并复用代码。目前已吸引85人学习下载适合准备电商数据分析类毕设、希望掌握大数据分析整体项目框架的学生或从业者参考。除了完整源码和数据集还提供论文级说明与迁移指南可帮助读者复现项目方法并在Hive数据分析、用户画像构建和可视化呈现等方面获得可直接落地的思路与实现。电商用户行为分析一套可以直接跑的数据分析源码说实话做数据分析这几年我见过太多“Excel拉个透视表就当用户分析”的项目。真要落地到用户分层、转化漏斗、留存预测这些业务动作上光靠几张静态报表根本不够。最近我把之前给某电商团队做的一套用户行为分析方案整理成了可运行的源码今天把整套思路和关键实现拆开讲一遍项目本身不大但数据清洗、RFM分层、漏斗转化、留存分析、商品偏好这些核心模块都齐了跑一遍就能用在自己项目上。适合刚接触用户增长分析的数据分析师也适合产品经理、运营同学拿去做参考更重要的是——源码可以直接跑不是那种贴了半截还得自己脑补的demo。1.1 这套源码到底能做什么先说清楚项目边界。这套分析基于的是电商平台最常见的用户行为日志数据就是那种每行记录一个用户行为的明细表包含用户ID、行为类型浏览、加购、收藏、支付、商品ID、行为时间、商品类目和金额字段。源码覆盖了从数据载入、清洗到产出分析结论的完整链路具体包括几个层面整体流量看板PV、UV、支付用户数、用户转化漏斗浏览→加购→收藏→支付、RFM用户价值分层、用户生命周期留存分析以及商品维度的品牌和品类偏好挖掘。每一块都有对应的代码、可视化图表和输出结果解释不是光画个图就完了每个分析结果旁边都附了“这个数字能指导什么业务动作”的解读。我做这套项目的核心动机其实很简单。市面上的用户行为分析要么用BI工具拖拽要么直接用付费分析平台对中小团队来说成本和灵活性都是问题。用Python写一套可复用、可改参数的分析脚本既能跑数据出结论又能随时增加分析维度源码在手里业务问题随时可以定制。这次开源出去的版本数据采用公开的电商行为数据集格式你可以直接从网上找到对应CSV来测也可以替换成自己业务库的导出数据只要字段对得上代码几乎不用大改。1.2 技术选型为什么是 Python Pandas 而不是别的先说一个很多新手会问的问题这套东西为什么不用SQL一把梭或者直接用Tableau答案是——分析场景不同。SQL适合固定口径的报表查询但一旦涉及RFM这种需要先算每个用户的R、F、M三个分值再分层又要把分层结果回写到明细数据里的复杂逻辑SQL写起来会非常绕。而Tableau这类BI工具做展示很顺手可它的计算逻辑是黑盒出了问题不好排查更没法方便地做批量回测和参数调优。这套源码我选的是Python 3.9 Pandas 2.0 Matplotlib/Seaborn的组合。Pandas处理千万行级别的数据完全没压力RFM这种分组聚合计算用groupby配合自定义函数几行就能搞定。可视化部分用Matplotlib和Seaborn是因为它们和Pandas的DataFrame无缝衔接直接传入列就能出图不需要额外的ETL。整个项目跑完一轮包括加载数据和生成全部图表在一台普通MacBook Pro上大约3分钟这个效率对于日常分析完全够用。提示如果你的数据量真正到了亿级那确实需要考虑Spark或者ClickHouse但对绝大多数电商团队来说Pandas纯内存计算反而是最省事、最容易调试的方案。2. 数据准备与核心指标拆解2.1 输入数据长什么样这套源码的核心输入是行为日志表和商品信息表。行为日志表我按最常见的电商埋点格式设计核心字段包括字段名含义示例值user_id用户ID100001behavior_type行为类型pv / cart / fav / buyitem_id商品ID2354category_id商品类目ID475timestamp行为时间毫秒级1511544070691brand_id品牌ID2891商品信息表则包含商品ID、类目、品牌、价格区间、上架时间等属性。两张表通过item_id关联。如果你是自己导数据把业务库里的订单表、日志表按照这个结构整理成CSV就行注意时间字段需要统一格式这个源码里我做了兼容处理秒级和毫秒级时间戳都能自动识别。这里有一个实际项目里特别容易踩坑的地方行为日志和订单数据经常是两个系统导出的用户ID的编码规则可能不一样。日志里是U12345带前缀的字符串订单里是纯数字两表一关联就会丢数据。我的建议是在数据清洗阶段就统一用户ID格式源码里专门写了格式化函数把所有ID统一转为整数类型避免后续所有分析的关联键不一致。2.2 核心指标的选取逻辑做用户行为分析最忌讳的就是指标堆砌。这套源码里我聚焦了五个核心分析维度每个维度对应的都是明确的业务问题第一流量与转化概览回答“平台当前的用户规模和转化效率是什么水平”。第二转化漏斗回答“用户在哪个环节流失最严重最值得优化”。第三RFM分层回答“哪些用户是高质量高价值用户哪些即将流失哪些是沉睡用户”。第四留存分析回答“各渠道进来的用户第一周、第二周、一个月后还剩下多少”。第五商品偏好回答“卖得好的商品集中在什么品类和品牌用户加购最多的是什么”。为什么是这几个指标而不是其他关键在于它们构成了一个闭环流量看整体现状漏斗找问题环节RFM做用户分群和精细化运营留存验证长期价值商品分析落到货品策略。这五块组合起来基本能覆盖电商运营周报里80%的数据需求。相比之下有些项目上来就算什么人均浏览深度、跳出率、页面停留时长这些指标不是没用而是它们更适合产品体验优化场景对当前这套以用户价值分析为核心的源码来说信息增益有限所以我在代码里刻意没有加入避免输出一大堆图表让读者抓不住重点。3. 核心代码实现从原始日志到业务洞察3.1 数据加载与清洗源码的第一步是数据载入这一步看似简单但里面有几个处理细节是新手上路最容易出问题的地方。时间戳的转换、数据去重、字段类型修正、异常值过滤这些前置动作做不好后面所有的分析口径都会歪。import pandas as pd import numpy as np from datetime import datetime # 读取行为日志和商品信息 behavior pd.read_csv(data/user_behavior.csv, sep,) items pd.read_csv(data/item_info.csv, sep,) # 时间戳统一处理兼容秒级和毫秒级 def convert_timestamp(ts): ts int(ts) if ts 10**12: # 毫秒级 return datetime.fromtimestamp(ts / 1000) return datetime.fromtimestamp(ts) behavior[event_time] behavior[timestamp].apply(convert_timestamp) behavior[event_date] behavior[event_time].dt.date # 去重防止埋点重复上报 behavior behavior.drop_duplicates().reset_index(dropTrue) # 过滤异常记录金额为负、用户ID为空等 behavior behavior[behavior[user_id].notna()] print(f清洗后数据量: {len(behavior):,} 行)这里我特别说明一下去重的逻辑。很多团队做用户分析的时候没有对原始日志做去重导致后面计算的PV虚高。实际操作中我发现同一个用户在短时间内对同一件商品的重复浏览可能是页面刷新造成的也可能是用户真的来回对比。源码里我给了一个保守的去重方案完全重复的记录直接删除如果想去掉更激进的去重比如用户5分钟内对同一商品重复浏览只算一次可以在代码里加一个时间窗口的groupby判断这个逻辑我注释在了代码中按需放开就行。3.2 RFM用户分层最经典的精细化运营模型RFM模型是整个源码里我最看重的一块。它的思路很简单用最近一次购买时间Recency、购买频率Frequency和购买金额Monetary三个维度给用户打分然后根据分数组合把用户分成不同层级。这套模型看起来简单但落地的时候有不少细节比如分数的阈值怎么定层级怎么命名不同行业的判断标准差异很大所以源码里我把阈值设成可配置参数。# 按用户聚合RFM指标 def compute_rfm(df): # 以当前数据最大日期作为基准日 current_date df[event_date].max() rfm df[df[behavior_type] buy].groupby(user_id).agg( recency(event_date, lambda x: (current_date - x.max()).days), frequency(event_date, count), monetary(amount, sum) ).reset_index() return rfm rfm_df compute_rfm(behavior) # 打分这里使用分位数切分避免人为硬编码阈值 def score_by_quantile(series, reverseFalse): qs series.quantile([0.25, 0.5, 0.75]) def score_val(v): if reverse: # recency越小越好 if v qs[0.25]: return 4 elif v qs[0.5]: return 3 elif v qs[0.75]: return 2 return 1 else: # frequency/monetary越大越好 if v qs[0.75]: return 4 elif v qs[0.5]: return 3 elif v qs[0.25]: return 2 return 1 return series.apply(score_val) rfm_df[r_score] score_by_quantile(rfm_df[recency], reverseTrue) rfm_df[f_score] score_by_quantile(rfm_df[frequency]) rfm_df[m_score] score_by_quantile(rfm_df[monetary]) # 分层规则 def rfm_segment(row): if row[r_score] 3 and row[f_score] 3 and 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] 3 and row[f_score] 2 and row[m_score] 2: return 新用户 elif row[r_score] 2 and row[f_score] 2 and row[m_score] 2: return 流失用户 else: return 潜力用户 rfm_df[segment] rfm_df.apply(rfm_segment, axis1)关于阈值切分我多说一句经验。很多教程直接告诉你R≤3天打4分、3-7天打3分这种固定规则但实际业务里不同品类的购买周期差异巨大——卖日用品的和卖大家电的购买频率根本不是一个量级。所以源码里我选择用分位数quantile切分让数据自己说话这样换一个数据集、换一个行业代码不用改分层逻辑依然成立。如果你有明确的业务经验比如运营明确告诉你“3个月内没复购就算流失”也可以直接把打分函数改成硬编码阈值这部分预留了修改接口。3.3 用户转化漏斗定位流失最严重的环节漏斗分析是电商运营的日常操作但很多人做的漏斗其实有个口径问题到底是用“会话”做漏斗还是用“用户”做漏斗用会话做漏斗适合分析单次访问的转化路径比如落地页→详情页→下单用用户做漏斗适合分析用户在整段时间内的行为转化比如浏览过商品的人里最终有多少人完成了支付。这套源码做的是用户级漏斗逻辑是把用户按行为类型分组统计每个环节的用户数再计算环节之间的转化率。# 用户级漏斗统计 funnel_data {} for behavior_type in [pv, cart, fav, buy]: user_count behavior[behavior[behavior_type] behavior_type][user_id].nunique() funnel_data[behavior_type] user_count funnel_df pd.DataFrame(list(funnel_data.items()), columns[stage, user_count]) funnel_df[conversion_rate] funnel_df[user_count] / funnel_df[user_count].iloc[0] * 100 funnel_df[step_rate] funnel_df[user_count].shift(1) / funnel_df[user_count] * 100这个漏斗的逻辑是先看有多少用户发生过浏览行为然后看这些用户里有多少加购再看多少收藏最后看多少完成支付。每一个环节的用户数都是独立统计的不是累计的——比如“加购用户数”指的是发生过加购行为的独立用户数而不是“浏览且加购”的用户数。两者各有适用场景但“独立用户数”更直观能直接回答“平台里到底有多少用户愿意加购”这个基础问题。从实践来看漏斗分析真正有价值的地方不在总转化率而在两个递进率之间的差值。比如浏览到加购的转化率是8%加购到支付的转化率是45%那说明用户加购意愿还行但支付转化不错问题可能出在商品详情页吸引力不够上反过来浏览到加购有20%加购到支付只有15%那说明详情页没问题但可能是价格、支付流程或者物流费用把用户劝退了。源码在输出漏斗图的同时也会自动打印每一个环节的递进转化率方便直接对照分析。3.4 留存分析与商品偏好留存分析这块源码按“日留存”和“周留存”两种维度计算。日留存适合看短期产品迭代效果和活动拉新质量周留存更适合看电商平台的自然留存水平因为电商用户的访问周期天然比内容产品要长。# 计算每个用户的活跃日期 user_active behavior[[user_id, event_date]].drop_duplicates() # 生成用户首日活跃日期 first_active user_active.groupby(user_id)[event_date].min().reset_index() first_active.columns [user_id, first_date] # 合并得到用户活跃日与首日的时间差天 user_cohort user_active.merge(first_active, onuser_id) user_cohort[days_diff] (user_cohort[event_date] - user_cohort[first_date]).dt.days # 留存矩阵 retention user_cohort[user_cohort[days_diff].between(0, 30)] retention_matrix retention.pivot_table( indexfirst_date, columnsdays_diff, valuesuser_id, aggfuncnunique, fill_value0 )留存矩阵的核心是以用户首次活跃日期为基准看这批用户在后续第N天还有多少人回来。实操中我一般会输出留存矩阵的热力图横轴是首次活跃后的第几天纵轴是首次活跃日期颜色深浅代表留存用户数或留存率。这里有一个关键细节每个日期的新用户基数不同直接比较用户数没有意义所以源码里会自动把留存矩阵转换成留存率每个格子除以当天的首日用户数这样不同日期的留存曲线才具有可比性。商品偏好分析相对简单。源码里按商品维度统计了浏览量、加购量、支付量然后计算“加购转化率”加购用户数/浏览用户数和“支付转化率”支付用户数/浏览用户数这两个指标能直接筛选出“高意向但低转化”的商品是运营做促销选品、客服做回访的黄金清单。同时在商品分析模块里我还加了品类维度的交叉分析帮助判断哪些品类的流量承接做得最好。3.5 可视化输出让分析结果自己说话说实话代码写得再漂亮最后业务方看不懂也是白搭。所以这套源码在可视化上花了心思输出全部自动保存为PNG图片到result目录并且每张图都做了中英文标签适配。核心图表包括每日PV/UV趋势折线图、用户转化漏斗图、RFM四象限散点图、留存热力图、商品类目Top10柱状图。import matplotlib.pyplot as plt import seaborn as sns plt.rcParams[font.sans-serif] [SimHei] # 支持中文显示 plt.rcParams[axes.unicode_minus] False # 每日PV/UV趋势 daily behavior.groupby(event_date).agg( pv(user_id, count), uv(user_id, nunique) ).reset_index() fig, ax1 plt.subplots(figsize(12, 6)) ax1.plot(daily[event_date], daily[pv], color#2E86AB, labelPV) ax1.plot(daily[event_date], daily[uv], color#A23B72, labelUV) ax1.set_xlabel(日期) ax1.set_ylabel(数量) ax1.legend() plt.title(每日PV/UV趋势, fontsize14) plt.xticks(rotation45) plt.tight_layout() plt.savefig(result/daily_trend.png, dpi150)如果你用的是Mac或者Linux服务器中文字体可能渲染不出来解决方法是把SimHei改成系统里已安装的中文字体名称或者干脆用英文标签。源码里我把字体设置放在一个config区域换环境改一处就行不用到处找。4. 运行环境与实操步骤4.1 依赖安装与目录结构项目运行环境非常简单Python 3.9以上版本安装Pandas、Matplotlib、Seaborn三个库就够了。建议使用虚拟环境隔离依赖conda create -n ecommerce_analysis python3.9 conda activate ecommerce_analysis pip install pandas matplotlib seaborn源码目录结构是这样的├── data/ │ ├── user_behavior.csv # 用户行为日志 │ └── item_info.csv # 商品信息表 ├── result/ # 分析结果输出目录 ├── config.py # 全局配置阈值、字体、路径 ├── data_process.py # 数据加载与清洗 ├── metrics.py # 指标计算RFM、漏斗、留存等 ├── visualization.py # 图表绘制 └── main.py # 主入口一键执行完整分析main.py是整个项目的调度中心顺序执行数据加载、清洗、指标计算、可视化最后输出一份汇总的CSV报告和所有图表。全程不需要任何人工干预非常适合放在服务器上定时跑比如每天凌晨自动更新运营报表。4.2 从零到一运行项目实际演示一遍。假设你已经把user_behavior.csv和item_info.csv放到了data目录下在项目根目录执行python main.py终端会依次输出数据加载的行数、清洗后剩余行数、RFM分层各类用户的数量、漏斗各环节的用户数和转化率、留存率的Top几行预览最后提示“分析完成结果已保存至result/目录”。整个流程走完大约2-3分钟取决于数据量的大小。我用一份100万行的公开数据集跑过一轮耗时1分48秒内存占用约1.2GB可以说相当克制了。如果你想把分析结果接入自己的报表系统可以修改main.py的末尾部分把CSV汇总结果写入MySQL或者发送到钉钉/企业微信机器人。源码里我预留了一个send_to_webhook的函数模板里面写了请求体的格式示例接入的时候只需要填上webhook地址和消息模板即可。5. 常见问题与排查技巧实录5.1 我踩过的那些坑这套源码在打磨过程中我先后遇到过几个比较典型的问题专门写出来供你参考。第一个坑是时间戳精度不一致。公开数据集里有一批时间戳是秒级另一批是毫秒级直接统一除以1000转换会导致一部分时间提前了约47年整个留存分析直接报废。排查过程其实不复杂——我先输出转换后时间的最大值和最小值发现最小值是1970年代立刻意识到是精度问题。解决方案就是我上面写的兼容性转换函数按数值大小判断精度这个问题算是解决了。第二个坑是内存溢出。我记得第一次跑全量2000万行数据的时候Pandas直接把16GB内存吃满了电脑风扇狂转。后来排查发现主要瓶颈在RFM计算那一步因为要对购买记录做多次groupby和merge。解决办法是优先过滤掉不需要的行比如只保留有购买行为的用户来做RFM而不是对全量行为做然后再计算。源码里我用了这个思路在compute_rfm函数里先df[df[behavior_type] buy]过滤再进入聚合性能提升非常明显。第三个坑是中文图表乱码。代码刚写完在Windows上跑一切正常换到Linux服务器直接变方块。原因是服务器上没有中文字体Matplotlib找不到合适的字体渲染。这个没什么技术含量但确实容易卡住新手解决方式是提前查一下系统有哪些字体如果连SimHei都没有就下载一个开源的文泉驿微米黑装完之后清除Matplotlib缓存再运行。5.2 问题排查速查表现象可能原因解决方法图表中文显示为方块系统缺少中文字体安装中文字体修改config.py字体配置留存矩阵中日期错乱时间戳精度不一致使用兼容转换函数统一转为datetime运行内存不足数据量过大先过滤无用字段分块读取或启用Pandas分块处理RFM分层结果全是同一类阈值切分失效检查是否有极端值尝试用log变换后再分位数漏斗转化率超过100%环节之间用户不是包含关系确认漏斗口径建议统计独立用户数秒级时间戳被识别成毫秒数值判断逻辑不正确检查threshold阈值设置10^12判断毫秒最后分享一个私藏技巧。跑完整个分析之后别急着关项目把daily_trend.png和retenion_heatmap.png拿给业务同事看的时候我习惯同时附上两份CSV一份是RFM分层后的用户明细表另一份是漏斗各环节用户数明细。这样运营同学可以直接用RFM分层表做用户包的圈选不需要自己再写一遍取数逻辑。我觉得一套分析源码的真正价值不只是出几张好看的图而是把分析结果变成业务方可直接使用的数据资产这才是电商用户行为分析该有的样子。本文还有配套的精品资源点击获取