ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Python电商用户行为分析实战:从RFM模型到漏斗分析与可视化

Python电商用户行为分析实战:从RFM模型到漏斗分析与可视化 最近在准备数据分析相关的面试和项目复盘时发现很多同学对电商用户行为分析这个经典场景既熟悉又陌生。熟悉的是概念陌生的是如何从零开始用Python完整地走一遍数据清洗、分析、建模到可视化的全流程。网上资料要么过于理论要么代码片段零散难以串联成一个可复现的实战项目。本文将以一个模拟的电商用户行为数据集为例手把手带你完成一个从原始数据到商业洞察的完整分析项目。你将掌握使用Pandas进行数据清洗与转换、应用RFM模型进行用户价值分层、通过漏斗分析洞察转化瓶颈并最终使用Matplotlib和Seaborn制作专业级可视化图表。所有代码均提供完整源码结构清晰注释详尽无论是用于课程设计、毕业项目还是丰富个人简历和面试作品集都能直接复用。1. 项目背景与核心价值在电商领域数据是驱动增长的核心引擎。用户每一次点击、浏览、加购、下单都留下了宝贵的行为痕迹。对这些行为数据进行系统分析能够回答一系列关键的商业问题我们的用户是谁他们在哪里流失哪些用户价值最高如何针对不同用户制定运营策略用户行为数据分析正是为了解决这些问题。它通过对用户在产品内的一系列操作日志进行收集、处理、分析和可视化来揭示用户行为模式、产品使用状况以及潜在的优化点。一个典型的分析流程包括数据获取、数据清洗、行为指标计算、模型构建如RFM和结果可视化。RFM模型是用户价值分层的经典方法它通过三个核心维度来评估客户价值RRecency用户最近一次消费时间。距离现在越近价值越高。FFrequency用户消费频率。在一定时间内购买次数越多价值越高。MMonetary用户消费金额。总消费金额越高价值越高。 通过将用户按R、F、M打分并分层我们可以识别出“重要价值用户”、“重要发展用户”、“重要保持用户”和“重要挽留用户”等不同群体从而实现精细化运营。漏斗分析则用于追踪用户在产品中达成目标的路径分析每一步的转化与流失情况。例如从“浏览商品”到“加入购物车”再到“生成订单”和“支付成功”形成一个标准的电商购买漏斗。通过分析各环节的转化率可以快速定位转化瓶颈优化产品流程。本实战项目将融合这些核心分析方法为你呈现一个端到端的Python数据分析案例。2. 环境准备与工具说明本项目主要使用Python的数据科学生态库。建议使用Anaconda来管理环境可以避免复杂的依赖问题。2.1 所需Python库及版本请确保你的Python环境建议使用Python 3.8及以上版本已安装以下库。你可以通过pip命令进行安装。# 核心数据处理与分析 pip install pandas1.5.3 numpy1.24.3 # 数据可视化 pip install matplotlib3.7.1 seaborn0.12.2 # 日期处理 pip install python-dateutil2.8.2 # 交互式图表可选用于更丰富的展示 # pip install plotly5.14.12.2 开发工具建议IDE/编辑器Jupyter Notebook (非常适合分步数据分析)、VS Code、PyCharm。数据文件我们将使用一个模拟生成的电商用户行为数据集user_behavior.csv。在真实项目中这份数据可能来自数据库导出或日志文件。2.3 项目目录结构建议在开始前建议创建如下目录结构使项目更加规范ecommerce_analysis_project/ │ ├── data/ # 存放数据文件 │ └── raw_user_behavior.csv │ ├── src/ # 存放源代码 │ ├── 01_data_loading_cleaning.py │ ├── 02_behavior_analysis.py │ ├── 03_rfm_analysis.py │ └── 04_visualization.py │ ├── output/ # 存放输出结果图表、报告 │ ├── figures/ │ └── reports/ │ └── main.py # 主程序用于串联整个流程3. 数据理解与加载我们首先需要理解数据并加载它。假设我们的原始数据raw_user_behavior.csv包含以下字段user_id: 用户唯一标识item_id: 商品IDbehavior_type: 行为类型 (pv: 浏览, cart: 加购, buy: 购买)item_category: 商品类别timestamp: 行为发生的时间戳格式2023-10-01 08:30:15price: 商品价格单位元3.1 加载数据与初步探索使用Pandas加载数据并进行初步探索了解数据规模、字段类型和是否存在缺失值。# 文件路径src/01_data_loading_cleaning.py import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns # 设置中文显示和图表样式 plt.rcParams[font.sans-serif] [SimHei, Arial Unicode MS, DejaVu Sans] # 用来正常显示中文标签 plt.rcParams[axes.unicode_minus] False # 用来正常显示负号 sns.set_style(whitegrid) # 1. 加载数据 df pd.read_csv(../data/raw_user_behavior.csv) print(数据形状行列:, df.shape) print(\n数据前5行:) print(df.head()) print(\n数据基本信息:) print(df.info()) print(\n数据描述性统计:) print(df.describe())运行上述代码你可能会看到类似以下输出数据形状行列: (100000, 6) 数据前5行: user_id item_id behavior_type item_category timestamp price 0 10001 20001 pv 手机 2023-10-01 08:30:15 2999.0 1 10001 20002 pv 电脑 2023-10-01 09:15:22 5999.0 2 10001 20001 cart 手机 2023-10-01 10:05:47 2999.0 3 10002 20003 pv 服饰 2023-10-01 11:20:33 199.0 4 10002 20003 cart 服饰 2023-10-01 12:10:18 199.0 数据基本信息: class pandas.core.frame.DataFrame RangeIndex: 100000 entries, 0 to 99999 Data columns (total 6 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 user_id 100000 non-null int64 1 item_id 100000 non-null int64 2 behavior_type 100000 non-null object 3 item_category 99995 non-null object 4 timestamp 100000 non-null object 5 price 99990 non-null float64 dtypes: float64(1), int64(2), object(3) memory usage: 4.6 MB None从info()可以看出item_category和price字段存在少量缺失值timestamp字段是对象类型字符串需要转换为日期时间类型。4. 数据清洗与预处理数据清洗是保证分析结果准确性的基石。本环节主要处理缺失值、异常值并转换数据类型。4.1 处理缺失值对于类别型字段item_category我们可以用众数或“未知”来填充。对于数值型字段price可以用中位数或均值填充这里我们根据业务场景选择中位数避免极端值影响。# 2. 处理缺失值 print(处理前缺失值统计:) print(df.isnull().sum()) # 填充item_category的缺失值为“未知” df[item_category].fillna(未知, inplaceTrue) # 填充price的缺失值为该商品所在类别的价格中位数更合理 # 如果无法按类别填充则使用全局中位数 if df[price].isnull().any(): # 先尝试按商品类别分组填充 category_median_price df.groupby(item_category)[price].transform(median) df[price] df[price].fillna(category_median_price) # 如果仍有缺失例如新类别所有价格都缺失用全局中位数填充 df[price].fillna(df[price].median(), inplaceTrue) print(\n处理后缺失值统计:) print(df.isnull().sum())4.2 转换数据类型与提取时间特征将timestamp转换为datetime类型并从中提取出年、月、日、小时、星期等特征便于后续按时间维度进行分析。# 3. 转换时间字段并提取特征 df[timestamp] pd.to_datetime(df[timestamp]) df[date] df[timestamp].dt.date df[year_month] df[timestamp].dt.to_period(M) # 年月如2023-10 df[day_of_week] df[timestamp].dt.dayofweek # 周一0, 周日6 df[hour] df[timestamp].dt.hour print(\n时间特征提取后数据示例:) print(df[[timestamp, date, year_month, day_of_week, hour]].head())4.3 处理异常值与数据一致性检查检查price是否有非正数behavior_type是否只有预期的几种类型。# 4. 异常值检查与处理 print(f价格小于等于0的记录数: {len(df[df[price] 0])}) # 假设价格为负或0是异常数据将其剔除或根据业务规则处理 df df[df[price] 0] print(f行为类型唯一值: {df[behavior_type].unique()}) # 确保行为类型只有 pv, cart, buy expected_behaviors [pv, cart, buy] df df[df[behavior_type].isin(expected_behaviors)] print(f清洗后数据形状: {df.shape})5. 用户行为分析数据清洗完成后我们可以开始计算一些核心的用户行为指标。5.1 基础指标计算计算每日/每月的PV页面浏览量、UV独立访客数、加购率、购买转化率等。# 文件路径src/02_behavior_analysis.py # 承接清洗后的df数据 # 1. 按日期统计基础指标 daily_metrics df.groupby(date).agg( pv(behavior_type, lambda x: (x pv).sum()), uv(user_id, nunique), cart_count(behavior_type, lambda x: (x cart).sum()), buy_count(behavior_type, lambda x: (x buy).sum()) ).reset_index() # 计算加购率加购UV / 浏览UV和购买转化率购买UV / 浏览UV # 注意这里计算的是UV级别的转化更精准 daily_pv_uv df[df[behavior_type] pv].groupby(date)[user_id].nunique().reset_index(namepv_uv) daily_cart_uv df[df[behavior_type] cart].groupby(date)[user_id].nunique().reset_index(namecart_uv) daily_buy_uv df[df[behavior_type] buy].groupby(date)[user_id].nunique().reset_index(namebuy_uv) daily_metrics daily_metrics.merge(daily_pv_uv, ondate, howleft) daily_metrics daily_metrics.merge(daily_cart_uv, ondate, howleft) daily_metrics daily_metrics.merge(daily_buy_uv, ondate, howleft) daily_metrics[cart_rate] daily_metrics[cart_uv] / daily_metrics[pv_uv] daily_metrics[buy_rate] daily_metrics[buy_uv] / daily_metrics[pv_uv] print(每日行为指标前5天:) print(daily_metrics.head())5.2 漏斗分析模型构建构建一个从“浏览(PV)” - “加购(Cart)” - “购买(Buy)”的经典电商漏斗。我们通常分析一个特定时间段如最近30天内完成整个流程的用户转化情况。# 2. 漏斗分析以最近30天数据为例 analysis_end_date df[date].max() analysis_start_date analysis_end_date - pd.Timedelta(days30) funnel_df df[(df[date] analysis_start_date) (df[date] analysis_end_date)] # 计算每一步的独立用户数 step1_users set(funnel_df[funnel_df[behavior_type] pv][user_id].unique()) step2_users set(funnel_df[funnel_df[behavior_type] cart][user_id].unique()) step3_users set(funnel_df[funnel_df[behavior_type] buy][user_id].unique()) # 计算转化 funnel_data { 步骤: [浏览(PV), 加购(Cart), 购买(Buy)], 用户数: [len(step1_users), len(step2_users), len(step3_users)] } funnel_df_summary pd.DataFrame(funnel_data) funnel_df_summary[转化率] funnel_df_summary[用户数] / funnel_df_summary[用户数].iloc[0] funnel_df_summary[步骤间转化率] funnel_df_summary[用户数].pct_change().fillna(0).apply(lambda x: 1x if x!0 else 0) # 简化计算 print(\n最近30天购买漏斗分析:) print(funnel_df_summary)6. RFM用户价值分层实战RFM分析是本次项目的核心。我们需要为每个用户计算R、F、M值然后进行打分和分层。6.1 计算用户RFM指标假设我们以analysis_end_date作为分析截止日期计算每个用户在此日期之前的R、F、M。# 文件路径src/03_rfm_analysis.py # 承接清洗后的df数据并定义分析截止日期 analysis_end_date df[date].max() print(f分析截止日期: {analysis_end_date}) # 筛选购买行为 buy_df df[df[behavior_type] buy].copy() # 计算每个用户的R、F、M rfm buy_df.groupby(user_id).agg( last_purchase_date(timestamp, max), # 最近一次购买时间 frequency(item_id, count), # 购买次数F monetary(price, sum) # 总消费金额M ).reset_index() # 计算RRecency距离分析截止日期的天数 rfm[recency] (pd.to_datetime(analysis_end_date) - rfm[last_purchase_date]).dt.days # 重命名列 rfm.rename(columns{frequency: frequency, monetary: monetary}, inplaceTrue) rfm rfm[[user_id, recency, frequency, monetary]] print(RFM原始数据前10位用户:) print(rfm.head(10)) print(f\n参与RFM分析的用户数有购买行为的用户: {len(rfm)})6.2 RFM打分与分层常用的打分方法有百分位数分箱如四分位或自定义阈值。这里我们使用四分位数将每个指标分为4个等级4分最高1分最低。# 对R、F、M分别进行打分使用分位数注意R越小越好所以打分逻辑相反 # R: 最近购买时间越近得分越高Recency越小越好 rfm[R_Score] pd.qcut(rfm[recency], q4, labels[4, 3, 2, 1]) # 注意qcut默认按值升序分箱recency越小标签4对应第一分箱 # 为了更清晰我们可以手动指定 r_labels range(4, 0, -1) # 4,3,2,1 rfm[R_Score] pd.qcut(rfm[recency], q4, labelsr_labels) # F和M: 值越大得分越高 rfm[F_Score] pd.qcut(rfm[frequency], q4, labels[1, 2, 3, 4]) rfm[M_Score] pd.qcut(rfm[monetary], q4, labels[1, 2, 3, 4]) # 将分数转换为整数类型方便后续计算 rfm[R_Score] rfm[R_Score].astype(int) rfm[F_Score] rfm[F_Score].astype(int) rfm[M_Score] rfm[M_Score].astype(int) # 计算RFM总分可选有时直接使用三维度组合 rfm[RFM_Score] rfm[R_Score].astype(str) rfm[F_Score].astype(str) rfm[M_Score].astype(str) print(\n打分后的RFM数据前10位用户:) print(rfm[[user_id, recency, frequency, monetary, R_Score, F_Score, M_Score, RFM_Score]].head(10))6.3 用户分层与标签定义根据R和F的得分我们可以定义一个经典的2x2用户分层矩阵并为每个用户打上标签。# 定义分层规则基于R_Score和F_Score def rfm_segment(row): if row[R_Score] 3 and row[F_Score] 3: return 重要价值用户 elif row[R_Score] 3 and row[F_Score] 3: return 重要发展用户 elif row[R_Score] 3 and row[F_Score] 3: return 重要保持用户 else: return 重要挽留用户 rfm[User_Segment] rfm.apply(rfm_segment, axis1) # 统计各分层用户数量 segment_counts rfm[User_Segment].value_counts() print(\nRFM用户分层统计:) print(segment_counts) print(f\n各分层占比:) print((segment_counts / len(rfm) * 100).round(2).astype(str) %)7. 数据可视化呈现分析结果需要通过图表直观展示。我们将使用Matplotlib和Seaborn绘制关键图表。7.1 每日核心指标趋势图# 文件路径src/04_visualization.py import matplotlib.pyplot as plt import seaborn as sns # 承接 daily_metrics 数据 plt.figure(figsize(14, 8)) # 子图1PV和UV趋势 plt.subplot(2, 2, 1) plt.plot(daily_metrics[date], daily_metrics[pv], labelPV浏览量, colorskyblue, markero) plt.plot(daily_metrics[date], daily_metrics[uv], labelUV独立访客, colorsalmon, markers) plt.xlabel(日期) plt.ylabel(数量) plt.title(每日PV与UV趋势) plt.legend() plt.xticks(rotation45) plt.grid(True, linestyle--, alpha0.7) # 子图2加购与购买数量趋势 plt.subplot(2, 2, 2) plt.plot(daily_metrics[date], daily_metrics[cart_count], label加购次数, colororange, marker^) plt.plot(daily_metrics[date], daily_metrics[buy_count], label购买次数, colorgreen, markerd) plt.xlabel(日期) plt.ylabel(数量) plt.title(每日加购与购买趋势) plt.legend() plt.xticks(rotation45) plt.grid(True, linestyle--, alpha0.7) # 子图3转化率趋势 plt.subplot(2, 2, 3) plt.plot(daily_metrics[date], daily_metrics[cart_rate], label加购率, colorpurple, marker*, linewidth2) plt.plot(daily_metrics[date], daily_metrics[buy_rate], label购买转化率, colorbrown, markerx, linewidth2) plt.xlabel(日期) plt.ylabel(转化率) plt.title(每日加购率与购买转化率) plt.legend() plt.xticks(rotation45) plt.grid(True, linestyle--, alpha0.7) plt.tight_layout() plt.savefig(../output/figures/daily_metrics_trend.png, dpi300, bbox_inchestight) plt.show()7.2 购买漏斗可视化# 承接 funnel_df_summary 数据 plt.figure(figsize(10, 6)) # 绘制漏斗图条形图模拟 steps funnel_df_summary[步骤] users funnel_df_summary[用户数] colors [#FF6B6B, #4ECDC4, #45B7D1] plt.barh(steps, users, colorcolors) plt.xlabel(用户数) plt.title(最近30天用户购买漏斗) # 在条形上添加数据标签 for i, v in enumerate(users): plt.text(v max(users)*0.01, i, f{v}\n({funnel_df_summary[转化率].iloc[i]:.1%}), vacenter) plt.gca().invert_yaxis() # 反转Y轴使第一步在最上面 plt.tight_layout() plt.savefig(../output/figures/purchase_funnel.png, dpi300, bbox_inchestight) plt.show()7.3 RFM用户分层分布图# 承接 rfm 数据 plt.figure(figsize(10, 6)) segment_order [重要价值用户, 重要发展用户, 重要保持用户, 重要挽留用户] segment_counts rfm[User_Segment].value_counts().reindex(segment_order) bars plt.bar(segment_counts.index, segment_counts.values, color[#2E86AB, #A23B72, #F18F01, #C73E1D]) plt.xlabel(用户分层) plt.ylabel(用户数量) plt.title(RFM用户分层分布) # 在柱子上添加数量和占比 for bar, count in zip(bars, segment_counts.values): height bar.get_height() percentage (count / len(rfm)) * 100 plt.text(bar.get_x() bar.get_width()/2., height max(segment_counts.values)*0.01, f{count}\n({percentage:.1f}%), hacenter, vabottom) plt.xticks(rotation15) plt.tight_layout() plt.savefig(../output/figures/rfm_segment_distribution.png, dpi300, bbox_inchestight) plt.show()7.4 RFM三维度分布与关系散点图# 绘制R、F、M的分布直方图 fig, axes plt.subplots(1, 3, figsize(15, 4)) metrics [recency, frequency, monetary] titles [最近消费间隔R分布, 消费频率F分布, 消费金额M分布] colors [skyblue, lightgreen, salmon] for idx, (metric, title, color) in enumerate(zip(metrics, titles, colors)): axes[idx].hist(rfm[metric], bins30, colorcolor, edgecolorblack, alpha0.7) axes[idx].set_xlabel(title.split()[0]) axes[idx].set_ylabel(用户数) axes[idx].set_title(title) axes[idx].grid(True, linestyle--, alpha0.5) plt.tight_layout() plt.savefig(../output/figures/rfm_histograms.png, dpi300, bbox_inchestight) plt.show() # 绘制F与M的散点图用R的大小着色 plt.figure(figsize(10, 6)) scatter plt.scatter(rfm[frequency], rfm[monetary], crfm[recency], cmapviridis_r, alpha0.6, s50) # viridis_r 使得颜色越浅代表R越小最近 plt.colorbar(scatter, label最近消费间隔R- 天数) plt.xlabel(消费频率F) plt.ylabel(消费金额M) plt.title(用户消费频率与金额关系颜色代表最近消费间隔) plt.grid(True, linestyle--, alpha0.3) plt.tight_layout() plt.savefig(../output/figures/f_m_scatter_by_r.png, dpi300, bbox_inchestight) plt.show()8. 项目总结与业务洞察通过以上完整的分析流程我们得到了以下关键结论和业务建议流量与转化健康度通过每日趋势图可以监控网站流量PV/UV和核心转化指标加购率、购买率的波动及时发现异常如某天转化率骤降。漏斗瓶颈定位漏斗分析清晰展示了从浏览到购买各环节的用户流失情况。如果“加购”到“购买”的转化率特别低可能需要优化购物车页面、支付流程或开展购物车营销如优惠券提醒。用户价值精细化运营RFM分层结果是我们最重要的产出。重要价值用户高R高F是平台的基石应提供VIP服务、专属优惠和新品优先体验致力于提升其忠诚度和生命周期总价值。重要发展用户高R低F是新用户或轻度用户但最近有互动。应通过个性化推荐、新手任务、低门槛优惠券等手段刺激其首次或二次购买提升消费频率。重要保持用户低R高F是过去的忠实用户但最近没来了。他们有高消费习惯流失可惜。应通过召回活动如推送他们可能感兴趣的商品、发放“好久不见”专属券进行唤醒。重要挽留用户低R低F是流失风险最高或已流失的用户。需要分析流失原因如价格、服务、竞品并尝试通过大力度的挽回策略如大额优惠券、积分兑换进行触达若无效则需考虑降低营销成本。9. 常见问题与排查思路在复现本项目或进行类似分析时你可能会遇到以下问题问题现象可能原因解决思路导入Pandas报错ModuleNotFoundErrorPython环境未安装pandas或不在正确的虚拟环境中。1. 确认激活了项目所用的虚拟环境如conda activate your_env。2. 使用pip list检查是否已安装。3. 使用pip install pandas安装。读取CSV文件报错FileNotFoundError文件路径错误。1. 检查文件是否存在于指定路径。2. 使用绝对路径或相对于当前运行脚本的正确相对路径。3. 在代码中使用os.path.exists(your_file.csv)验证路径。时间转换错误OutOfBoundsDatetime时间戳数据格式异常或包含极值如1970年以前。1. 使用df[timestamp].head()查看原始格式。2. 尝试指定格式pd.to_datetime(df[timestamp], format%Y-%m-%d %H:%M:%S)。3. 使用errorscoerce参数将错误格式转为NaT再处理这些异常行。RFM打分时qcut报错Bin edges must be unique数据中用于分箱的列存在大量重复值导致无法划分出指定数量的分位数箱。1. 检查数据的唯一值数量是否少于分箱数q。2. 使用pd.cut指定自定义的数值区间进行分箱。3. 减少分箱数量q的值。可视化图表中文显示为方框系统未安装中文字体或Matplotlib未配置中文字体。1. 使用本文代码中的plt.rcParams设置。2. 下载中文字体如SimHei.ttf并添加到Matplotlib字体目录或在代码中指定字体文件路径。分析结果中用户数异常少数据过滤条件过于严格或原始数据中购买行为记录本身就很少。1. 检查数据清洗步骤是否误删了大量购买记录。2. 确认analysis_end_date设置是否正确是否包含了所有要分析的数据。3. 回顾业务逻辑购买行为定义是否准确。10. 最佳实践与项目扩展建议10.1 工程化与代码优化函数化与模块化将数据加载、清洗、RFM计算、可视化等步骤封装成独立的函数或类提高代码可读性和复用性。可以创建一个RFMAnalyzer类。配置文件管理将数据库连接信息、文件路径、分析参数如RFM分箱规则、分析时间段抽取到配置文件如config.yaml或config.ini中避免硬编码。日志记录使用Python的logging模块记录程序运行状态、警告和错误信息便于后期调试和监控。单元测试为核心的数据处理函数和计算逻辑编写单元测试确保代码的健壮性。10.2 分析深度扩展结合更多维度除了RFM可以引入更多维度如商品类别偏好通过item_category、浏览深度、访问时长等构建更精细的用户画像。时间序列预测利用历史每日的PV、UV、GMV等数据使用ARIMA、Prophet或LSTM等模型进行未来趋势预测。用户聚类分析使用K-Means、DBSCAN等聚类算法基于用户行为特征如各行为次数、时间分布等进行无监督聚类发现数据驱动的用户分群可能与RFM分层结果相互验证或补充。关联规则分析使用Apriori或FP-Growth算法分析“购买了A商品的用户也经常购买B商品”这样的关联规则用于商品推荐和捆绑销售。10.3 部署与自动化自动化报告使用Jupyter Notebook的nbconvert或Papermill将分析流程自动化并生成HTML/PDF格式的分析报告。定时任务使用Apache Airflow、Celery或操作系统的Cron任务定期如每天/每周自动运行分析脚本将最新结果更新到看板或发送邮件。交互式看板使用Plotly Dash、Streamlit或Grafana等工具将核心指标和图表构建成可交互的Web看板方便业务人员随时查看。本项目提供了一个坚实的起点涵盖了从数据到洞察的完整链路。你可以在此基础上根据实际业务数据和需求进行修改和深化将其打造成一个真正具有商业价值的数据分析项目。
返回列表