Python 电商订单全流程分析:数据清洗 + 多维度可视化 + LRFM+K-Means 用户分群(附完整可运行代码)
一、博客摘要
本文基于真实电商订单数据集 order2021kmeans.xlsx,使用 Pandas、Matplotlib、Pyecharts、Scikit-learn 实现数据清洗、多维度营收可视化、月度退款分析、LRFM 用户特征构建、K-Means 聚类用户分群、交互式图表画像 全套实战。适合 Python 数据分析初学者、电商运营、机器学习入门学习者,所有代码可直接复制运行,同时标注踩坑点与业务解读,落地性极强。
技术栈:Python、Pandas(数据处理)、Matplotlib(静态可视化)、Pyecharts(交互式图表)、K-Means(无监督聚类) 实现功能:缺失值 / 异常值清洗、渠道 / 月度 / 时段收益分析、月度退款趋势、LRFM 特征工程、手肘法选 K 值、用户聚类分群、饼图 / 雷达图用户画像可视化
二、环境准备与依赖安装
2.1 导入基础库 & 全局配置
解决 Matplotlib 中文乱码、忽略运行警告,是数据分析项目通用前置配置。
python
运行
# 导入数据分析、可视化基础库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
# 导入pyecharts所有图表及配置项
from pyecharts.charts import *
from pyecharts import options as opts
# 忽略代码运行警告
import warnings
warnings.filterwarnings('ignore')
# 全局设置:Matplotlib中文显示 + 负号正常展示
mpl.rcParams['font.sans-serif']=['SimHei']
mpl.rcParams['axes.unicode_minus']=False
2.2 安装第三方依赖
若未安装pyecharts等库,在 Jupyter Notebook/CMD 终端执行以下命令:
bash
运行
pip install pyecharts pandas numpy matplotlib scikit-learn openpyxl
提示:
openpyxl用于读取 Excel 文件,缺少会导致pd.read_excel报错;安装完成后重启 Jupyter 内核生效。
三、数据加载与探索性分析
3.1 读取数据 & 查看基础信息
数据集包含 10 万 + 电商订单数据,涵盖订单、用户、渠道、时间、金额、退款等核心字段。
python
运行
# 读取Excel订单数据(文件需和代码放在同一目录)
df = pd.read_excel('order2021kmeans.xlsx')
# 查看前5行数据
df.head()
# 查看数据结构、字段类型、非空数量
df.info()
# 数值型字段描述性统计(均值、最值、分位数)
df.describe()
# 统计重复行数量
print("数据重复行数:", df.duplicated().sum())
# 统计全表缺失值
print("原始数据各字段缺失值统计:")
print(df.isnull().sum())
字段说明
- 基础标识:订单顺序编号、订单号、用户名、商品编号
- 金额指标:订单金额、付款金额(核心营收字段)
- 渠道平台:渠道编号、平台类型(微信公众号 / APP)
- 时间字段:下单时间、付款时间(datetime 时间格式)
- 订单状态:是否退款(区分有效订单与退款订单)
3.2 数据清洗(处理异常值 + 缺失值)
原始数据存在付款金额负数(退款异常)、渠道编号缺失问题,必须清洗后再分析。
python
运行
# 1. 处理付款金额负数异常值:取绝对值
df['付款金额'] = df['付款金额'].abs()
# 2. 删除含缺失值的行(渠道编号缺失无法做渠道分析)
df.dropna(inplace=True)
# 清洗后再次校验缺失值
print("清洗后缺失值统计:")
print(df.isnull().sum())
四、多维度营收可视化分析
4.1 按渠道划分收益(柱状图 + 玫瑰饼图)
统计各渠道总营收,分析核心盈利渠道,结合静态柱状图 + 交互式玫瑰图双重展示。
4.1.1 渠道收益柱状图
python
运行
# 按渠道分组,汇总付款金额并降序排序
channel_revenue = df.groupby('渠道编号')['付款金额'].sum().sort_values(ascending=False).reset_index()
# 绘制柱状图
plt.figure(figsize=(10,8))
plt.bar(channel_revenue['渠道编号'], channel_revenue['付款金额'])
plt.xticks(rotation=45) # X轴标签旋转,防止文字重叠
plt.title('按渠道划分的收益')
plt.xlabel('渠道编号')
plt.ylabel('收益')
plt.tight_layout() # 自动适配布局,避免标签截断
plt.show()
4.1.2 渠道收益交互式玫瑰饼图
使用 Pyecharts 绘制南丁格尔玫瑰图,鼠标悬浮可查看具体数值。
python
运行
# 适配pyecharts数据格式:二维列表
data = [list(z) for z in zip(channel_revenue['渠道编号'], channel_revenue['付款金额'])]
# 绘制环形玫瑰饼图
pie = (
Pie()
.add('渠道收益', data, rosetype='radius', radius=["20%","60%"])
.set_global_opts(title_opts=opts.TitleOpts(title='按渠道划分的收益'))
)
# Jupyter中渲染图表
pie.render_notebook()
4.2 按月份划分整体收益
从付款时间提取月份,分析全年 1-12 月营收趋势。
python
运行
# 从时间字段提取月份(1-12)
df['月份'] = df['付款时间'].dt.month
# 按月份分组统计总收益
month_revenue = df.groupby('月份')['付款金额'].sum().reset_index()
# 绘制月度收益柱状图
plt.figure(figsize=(10,8))
plt.bar(month_revenue['月份'], month_revenue['付款金额'])
plt.xticks(range(1,13)) # 强制展示1-12所有月份
plt.title('按月份划分的收益')
plt.xlabel('月份')
plt.ylabel('收益')
plt.tight_layout()
plt.show()
4.3 每日小时级收益分析(时段消费规律)
筛选非退款有效订单,拆分 24 小时时段,分析用户下单高峰。
python
运行
# 筛选非退款订单(有效成交订单)
data = df.loc[df['是否退款'] == '否']
# 提取时间衍生字段:小时、日期、英文星期
data['付款小时'] = data['付款时间'].dt.hour
data['付款天数'] = data['付款时间'].dt.day
data['付款天数名称'] = data['付款时间'].dt.day_name()
# 按【星期+小时】分组,统计时段收益
hourly_sales = data.groupby(['付款天数名称','付款小时'])['付款金额'].sum().reset_index()
# 重命名字段
hourly_sales = hourly_sales.rename(columns={'付款金额': 'TotalValue'})
# 按24小时为一组拆分数据(一天24个时段)
split_dfs = []
num_groups = len(hourly_sales) // 24
for i in range(num_groups):
start_index = i * 24
end_index = start_index + 24
split_df = hourly_sales.iloc[start_index:end_index]
split_dfs.append(split_df)
# 查看第一天24小时数据
print("第一天24小时收益数据:")
print(split_dfs[0])
# 绘制多日小时收益折线图
name = hourly_sales['付款天数名称'].unique()
line = (
Line(init_opts=opts.InitOpts(width="1000px", height="600px"))
.add_xaxis(split_dfs[0]['付款小时'].astype(str).tolist())
.set_global_opts(
title_opts={"text":"每日每小时收益总额"},
legend_opts=opts.LegendOpts(orient='vertical', pos_top='5%', pos_right='5%')
)
)
# 循环添加每日折线
for i in range(num_groups):
line.add_yaxis(name[i], split_dfs[i]['TotalValue'].tolist(), label_opts=opts.LabelOpts(is_show=False))
line.render_notebook()
4.4 月度退款金额趋势分析
单独提取退款订单,统计每月退款总额,监控售后风险。
python
运行
# 复用已提取的月份字段,筛选退款订单
data_refund = df.loc[df['是否退款'] == '是']
# 按月份汇总退款金额
refund = data_refund.groupby('月份')['付款金额'].sum()
# 绘制退款趋势折线图
refund.plot(kind='line',title='每个月份退款金额')
plt.show()
五、LRFM 用户特征工程(用户分群核心)
基于传统 RFM 模型扩展为LRFM,从 4 个维度量化用户消费行为,为聚类模型提供特征:
- L:用户最大消费时间 - 最小消费时间(用户消费周期)
- R:最近一次消费距离数据集最晚时间的天数(用户活跃度)
- F:用户订单总数量(消费频次)
- M:用户累计消费总金额(用户价值)
python
运行
# 1. 计算L指标:用户两次消费的时间间隔(天数)
L = (data.groupby('用户名')['付款时间'].max() - data.groupby('用户名')['付款时间'].min()).dt.days.reset_index()
# 2. 计算R指标:最近消费距离数据集最大日期的天数
data['付款时间'] = pd.to_datetime(data['付款时间'])
max_date = max(data['付款时间'])
data['diff'] = max_date - data['付款时间']
data['diff'] = data['diff'].dt.days
R = data.groupby('用户名')['diff'].min().reset_index()
# 3. 计算F指标:用户订单总数
F = data.groupby('用户名')['订单号'].count().reset_index()
# 4. 计算M指标:用户累计消费金额
M = data.groupby('用户名')['付款金额'].sum().reset_index()
# 多表合并,生成LRFM完整数据集
LRFMdata = L.merge(R).merge(F).merge(M)
# 规范列名
LRFMdata.columns = ['用户名','L','R','F','M']
# 查看特征数据
LRFMdata.head()
六、数据标准化(K-Means 前置必备)
K-Means 基于欧式距离计算,不同特征数值量级差距过大会导致模型偏倚,使用 MinMaxScaler 将数据缩放到 [0,1] 区间。
python
运行
# 备份原始数据,防止数据污染
model_data = LRFMdata.copy()
# 提取L/R/F/M 4个特征列(剔除用户名字符串列)
scale_matrix = model_data.iloc[:, 1:5]
# 导入归一化工具
from sklearn.preprocessing import MinMaxScaler
model_scaler = MinMaxScaler()
# 执行归一化转换
data_scaled = model_scaler.fit_transform(scale_matrix)
# 输出保留3位小数的归一化结果
print("归一化后特征数据:")
print(data_scaled.round(3))
七、手肘法确定 K-Means 最优聚类数
通过手肘法计算不同 K 值对应的 SSE(簇内误差平方和),曲线拐点即为最优聚类数量。
python
运行
from sklearn.cluster import KMeans
# 存储不同K值的SSE
SSE = []
# 遍历K=1~9,训练模型
for i in range(1,10):
kmeans = KMeans(n_clusters = i, random_state = 10)
kmeans.fit(data_scaled)
SSE.append(kmeans.inertia_)
# 绘制手肘图
plt.figure(figsize=(8,6))
plt.plot(range(1,10), SSE, marker = 'o', color='red')
plt.title('手肘法确定最优K值')
plt.xlabel('聚类数量 K')
plt.ylabel('SSE(簇内误差平方和)')
plt.grid(True)
plt.show()
业务解读:本案例曲线拐点为 K=3,最终将用户分为 3 个群体。
八、K-Means 模型训练 & 标签合并
根据最优 K 值训练聚类模型,将聚类标签合并回原始 LRFM 数据集。
python
运行
# 设置聚类数量为3
n_clusters = 3
# 初始化并训练模型,同时预测聚类标签
model_kmeans = KMeans(n_clusters=n_clusters, random_state=10)
cluster_labels_k = model_kmeans.fit_predict(data_scaled)
# 将聚类标签绑定到原始数据
LRFMdata['Cluster_Id'] = cluster_labels_k
merge_data = LRFMdata.copy()
九、聚类结果统计与可视化(用户画像)
9.1 各用户群体指标统计
计算每个聚类的 L/R/F/M 均值、群体人数,初步分析群体特征。
python
运行
# 筛选分析字段
merged_lrfm = merge_data[['M','F','R','L','Cluster_Id']]
# 按聚类分组,计算各指标均值
mean_lrfm = merged_lrfm.groupby('Cluster_Id').mean().reset_index()
# 统计每个群体的用户数量
mean_lrfm['count'] = merged_lrfm['Cluster_Id'].value_counts().values
# 输出统计结果
print("各用户群体特征均值 & 人数统计:")
print(mean_lrfm)
9.2 聚类人数占比环形饼图
可视化 3 类用户的人数分布占比。
python
运行
# 构造饼图数据
data_lrfm = [list(z) for z in zip(mean_lrfm['Cluster_Id'], mean_lrfm['count'])]
# 绘制环形饼图
pie_lrfm = (
Pie()
.add('每种分类人数占比', data_lrfm, radius=["35%","50%"])
.set_global_opts(title_opts=opts.TitleOpts(title="每种分类人数占比"))
)
pie_lrfm.render_notebook()
9.3 用户分群特征雷达图(核心画像)
使用雷达图直观对比 3 类用户在 L、R、F、M 四个维度的差异,完成最终用户分层。
python
运行
from pyecharts import options as opts
from pyecharts.charts import Radar
# 1. 定义雷达图维度
dims = ['M', 'F', 'R', 'L']
# 2. 自动计算维度最大值,设置雷达图边界
indicators = []
for dim in dims:
max_val = mean_lrfm[dim].max() * 1.1 # 放大1.1倍,避免图形顶格
indicators.append(opts.RadarIndicatorItem(name=dim, max_=max_val))
# 3. 提取3个聚类的特征数据
cluster_0_data = mean_lrfm[mean_lrfm['Cluster_Id'] == 0][dims].values[0].tolist()
cluster_1_data = mean_lrfm[mean_lrfm['Cluster_Id'] == 1][dims].values[0].tolist()
cluster_2_data = mean_lrfm[mean_lrfm['Cluster_Id'] == 2][dims].values[0].tolist()
# 4. 绘制多组雷达图
c = (
Radar(init_opts=opts.InitOpts(width="800px", height="600px"))
.add_schema(schema=indicators)
# 第一类用户
.add(
"Cluster 0",
[cluster_0_data],
color="#FF0000",
linestyle_opts=opts.LineStyleOpts(color="#FF0000"),
)
# 第二类用户
.add(
"Cluster 1",
[cluster_1_data],
color="#0000FF",
linestyle_opts=opts.LineStyleOpts(color="#0000FF"),
)
# 第三类用户
.add(
"Cluster 2",
[cluster_2_data],
color="#008000",
linestyle_opts=opts.LineStyleOpts(color="#008000"),
)
# 隐藏数据标签、配置标题与图例
.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
.set_global_opts(
title_opts=opts.TitleOpts(title="用户分群特征雷达图"),
legend_opts=opts.LegendOpts(pos_top="10%"),
)
)
c.render_notebook()
十、完整整合代码(一键复制运行)
将所有代码按执行顺序整合,直接复制到 Jupyter Notebook 即可运行(确保order2021kmeans.xlsx与代码同目录)。
python
运行
# ===================== 电商订单数据分析+LRFM+K-Means聚类 完整代码 =====================
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
from pyecharts.charts import *
from pyecharts import options as opts
import warnings
warnings.filterwarnings('ignore')
# 解决Matplotlib中文乱码
mpl.rcParams['font.sans-serif']=['SimHei']
mpl.rcParams['axes.unicode_minus']=False
# 1. 数据加载与探索
df = pd.read_excel('order2021kmeans.xlsx')
df.head()
df.info()
df.describe()
print("重复行数:", df.duplicated().sum())
print("原始缺失值:")
print(df.isnull().sum())
# 2. 数据清洗
df['付款金额'] = df['付款金额'].abs()
df.dropna(inplace=True)
print("清洗后缺失值:")
print(df.isnull().sum())
# 3. 渠道收益分析 柱状图
channel_revenue = df.groupby('渠道编号')['付款金额'].sum().sort_values(ascending=False).reset_index()
plt.figure(figsize=(10,8))
plt.bar(channel_revenue['渠道编号'], channel_revenue['付款金额'])
plt.xticks(rotation=45)
plt.title('按渠道划分的收益')
plt.xlabel('渠道编号')
plt.ylabel('收益')
plt.tight_layout()
plt.show()
# 渠道收益 玫瑰饼图
data = [list(z) for z in zip(channel_revenue['渠道编号'], channel_revenue['付款金额'])]
pie = (Pie().add('渠道收益', data, rosetype='radius', radius=["20%","60%"]).set_global_opts(title_opts=opts.TitleOpts(title='按渠道划分的收益')))
pie.render_notebook()
# 4. 月度整体收益分析
df['月份'] = df['付款时间'].dt.month
month_revenue = df.groupby('月份')['付款金额'].sum().reset_index()
plt.figure(figsize=(10,8))
plt.bar(month_revenue['月份'], month_revenue['付款金额'])
plt.xticks(range(1,13))
plt.title('按月份划分的收益')
plt.xlabel('月份')
plt.ylabel('收益')
plt.tight_layout()
plt.show()
# 5. 小时级收益分析
data = df.loc[df['是否退款'] == '否']
data['付款小时'] = data['付款时间'].dt.hour
data['付款天数'] = data['付款时间'].dt.day
data['付款天数名称'] = data['付款时间'].dt.day_name()
hourly_sales = data.groupby(['付款天数名称','付款小时'])['付款金额'].sum().reset_index()
hourly_sales = hourly_sales.rename(columns={'付款金额': 'TotalValue'})
split_dfs = []
num_groups = len(hourly_sales) // 24
for i in range(num_groups):
start_index = i * 24
end_index = start_index + 24
split_df = hourly_sales.iloc[start_index:end_index]
split_dfs.append(split_df)
print(split_dfs[0])
name = hourly_sales['付款天数名称'].unique()
line = (Line(init_opts=opts.InitOpts(width="1000px", height="600px")).add_xaxis(split_dfs[0]['付款小时'].astype(str).tolist()).set_global_opts(title_opts={"text":"每日每小时收益总额"},legend_opts=opts.LegendOpts(orient='vertical', pos_top='5%', pos_right='5%')))
for i in range(num_groups):
line.add_yaxis(name[i], split_dfs[i]['TotalValue'].tolist(), label_opts=opts.LabelOpts(is_show=False))
line.render_notebook()
# 6. 月度退款分析
data_refund = df.loc[df['是否退款'] == '是']
refund = data_refund.groupby('月份')['付款金额'].sum()
refund.plot(kind='line',title='每个月份退款金额')
plt.show()
# 7. 构建LRFM特征
L = (data.groupby('用户名')['付款时间'].max() - data.groupby('用户名')['付款时间'].min()).dt.days.reset_index()
data['付款时间'] = pd.to_datetime(data['付款时间'])
max_date = max(data['付款时间'])
data['diff'] = max_date - data['付款时间']
data['diff'] = data['diff'].dt.days
R = data.groupby('用户名')['diff'].min().reset_index()
F = data.groupby('用户名')['订单号'].count().reset_index()
M = data.groupby('用户名')['付款金额'].sum().reset_index()
LRFMdata = L.merge(R).merge(F).merge(M)
LRFMdata.columns = ['用户名','L','R','F','M']
LRFMdata.head()
# 8. 数据标准化
model_data = LRFMdata.copy()
scale_matrix = model_data.iloc[:, 1:5]
from sklearn.preprocessing import MinMaxScaler
model_scaler = MinMaxScaler()
data_scaled = model_scaler.fit_transform(scale_matrix)
print(data_scaled.round(3))
# 9. 手肘法选最优K值
from sklearn.cluster import KMeans
SSE = []
for i in range(1,10):
kmeans = KMeans(n_clusters = i, random_state = 10)
kmeans.fit(data_scaled)
SSE.append(kmeans.inertia_)
plt.figure(figsize=(8,6))
plt.plot(range(1,10), SSE, marker = 'o', color='red')
plt.title('手肘法确定最优K值')
plt.xlabel('聚类数量 K')
plt.ylabel('SSE(簇内误差平方和)')
plt.grid(True)
plt.show()
# 10. K-Means模型训练
n_clusters = 3
model_kmeans = KMeans(n_clusters=n_clusters, random_state=10)
cluster_labels_k = model_kmeans.fit_predict(data_scaled)
LRFMdata['Cluster_Id'] = cluster_labels_k
merge_data = LRFMdata.copy()
# 11. 聚类统计分析
merged_lrfm = merge_data[['M','F','R','L','Cluster_Id']]
mean_lrfm = merged_lrfm.groupby('Cluster_Id').mean().reset_index()
mean_lrfm['count'] = merged_lrfm['Cluster_Id'].value_counts().values
print(mean_lrfm)
# 12. 聚类人数占比饼图
data_lrfm = [list(z) for z in zip(mean_lrfm['Cluster_Id'], mean_lrfm['count'])]
pie_lrfm = (Pie().add('每种分类人数占比', data_lrfm, radius=["35%","50%"]).set_global_opts(title_opts=opts.TitleOpts(title="每种分类人数占比")))
pie_lrfm.render_notebook()
# 13. 用户分群雷达图
dims = ['M', 'F', 'R', 'L']
indicators = []
for dim in dims:
max_val = mean_lrfm[dim].max() * 1.1
indicators.append(opts.RadarIndicatorItem(name=dim, max_=max_val))
cluster_0_data = mean_lrfm[mean_lrfm['Cluster_Id'] == 0][dims].values[0].tolist()
cluster_1_data = mean_lrfm[mean_lrfm['Cluster_Id'] == 1][dims].values[0].tolist()
cluster_2_data = mean_lrfm[mean_lrfm['Cluster_Id'] == 2][dims].values[0].tolist()
c = (
Radar(init_opts=opts.InitOpts(width="800px", height="600px"))
.add_schema(schema=indicators)
.add("Cluster 0",[cluster_0_data],color="#FF0000",linestyle_opts=opts.LineStyleOpts(color="#FF0000"))
.add("Cluster 1",[cluster_1_data],color="#0000FF",linestyle_opts=opts.LineStyleOpts(color="#0000FF"))
.add("Cluster 2",[cluster_2_data],color="#008000",linestyle_opts=opts.LineStyleOpts(color="#008000"))
.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
.set_global_opts(title_opts=opts.TitleOpts(title="用户分群特征雷达图"),legend_opts=opts.LegendOpts(pos_top="10%"))
)
c.render_notebook()
十一、项目总结 & 踩坑避坑指南
11.1 业务总结
- 数据层:完成 10 万 + 订单数据清洗,解决缺失值、负数异常值,保障数据质量;
- 可视化层:从渠道、月份、小时、退款 4 个维度完成营收分析,定位核心渠道、消费高峰、售后风险月份;
- 特征层:基于业务构建 LRFM 四维用户特征,量化用户消费行为;
- 模型层:使用手肘法确定最优聚类数,通过 K-Means 实现用户自动分群;
- 运营落地:结合统计表、饼图、雷达图完成用户画像,可针对不同群体制定差异化营销方案(高价值用户维系、沉睡用户召回、普通用户转化)。
11.2 高频踩坑点(新手必看)
- 中文乱码:Matplotlib 必须配置
SimHei黑体,否则中文显示为方框; - 时间字段报错:时间列必须为
datetime格式,才能使用.dt提取月份、小时; - K-Means 报错 / 结果异常:必须做数据标准化,金额等大数值字段会主导聚类结果;
- Pyecharts 渲染问题:Jupyter 使用
render_notebook(),普通.py文件使用render("xxx.html"); - 变量未定义:重启 Jupyter 内核后,需从上到下依次运行代码,避免变量丢失。
十二、CSDN 发布补充(标签 + 分类)
- 博客标题:Python 电商订单数据分析实战 | 数据清洗 + 可视化 + LRFM+K-Means 用户分群(完整代码)
- 标签:Python 数据分析、KMeans 聚类、RFM 模型、电商分析、Pandas、Pyecharts
- 文章分类:Python、数据分析、机器学习实战
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)