# 勤奋的凯尔森同学10000h刻意练习Day5:综合应用案例——Kaggle电商客户行为分析

所属专栏: 凯尔森的10000h刻意练习
Slogan: 一个36岁程序员, 研究生(学硕),前世界500强top20软件开发Java工程师,用10000小时深耕AI, 目标Top10 AI资深工程师, 全程日更记录。
tips: 文章末尾附有jupyter完整代码

在学习了NumPy、Pandas以及多种可视化工具后,我们通过一个真实的Kaggle数据集来串联所有知识点。本案例将使用E-Commerce Customer Behavior & Sales Dataset - TR(土耳其电商客户行为数据集),该数据集包含5000条真实交易记录,涵盖了客户demographics、购买行为、产品偏好和engagement指标等多个维度。

# 1.1 案例背景与目标

数据集来源:Kaggle平台上的"E-Commerce Customer Behavior & Sales Analysis -TR"数据集,我们使用的是ecommerce_customer_behavior_dataset.csv这个文件,还有一个ecommerce_customer_behavior_dataset_v2.csv的版本,数据量有1.7W+。

数据集概览:

  • 记录数:5000条交易记录
  • 时间范围:2023年1月至2024年3月
  • 字段数:18列
  • 数据质量:无缺失值,格式一致

字段说明:

字段名 类型 说明
Order_ID 字符串 唯一订单标识
Customer_ID 字符串 唯一客户标识
Date 日期 交易日期
Age 整数 客户年龄(18-75岁)
Gender 字符串 性别(Male/Female/Other)
City 字符串 客户所在城市
Product_Category 字符串 产品类别(8类)
Unit_Price 浮点数 单价
Quantity 整数 购买数量(1-5)
Discount_Amount 浮点数 折扣金额
Total_Amount 浮点数 最终支付金额
Payment_Method 字符串 支付方式
Device_Type 字符串 设备类型(Mobile/Desktop/Tablet)
Session_Duration_Minutes 整数 会话时长(1-120分钟)
Pages_Viewed 整数 浏览页面数(1-50)
Is_Returning_Customer 布尔值 是否回头客
Delivery_Time_Days 整数 配送天数(1-30天)
Customer_Rating 整数 客户评分(1-5星)

分析目标:

  1. 客户画像分析:了解不同年龄、性别、地区的客户消费特征
  2. 销售趋势分析:识别季节性模式和销售高峰期
  3. 产品类别表现:比较各类别的销售额、评分和退货情况
  4. 设备行为分析:不同设备类型的购买行为差异
  5. 客户忠诚度分析:回头客与新客户的行为对比
  6. 配送与满意度关系:分析配送时间对客户评分的影响

# 1.2 数据获取与加载

# 1.2.1 从Kaggle下载数据集

方式一:直接从Kaggle网站下载

  1. 访问https://www.kaggle.com/datasets/umuttuygurr/e-commerce-customer-behavior-and-sales-analysis-tr
  2. 点击"Download"按钮下载CSV文件

方式二:使用Kaggle API(推荐,便于复现)

# 安装Kaggle API
pip install kaggle

# 配置API凭证(需要先在Kaggle账号中创建API token)
# 将下载的kaggle.json放在/Users/kelsen/Code/Jupyter/目录下

# 下载数据集
kaggle datasets download -d umuttuygurr/e-commerce-customer-behavior-and-sales-analysis-tr -p /Users/kelsen/Code/Jupyter/
# 解压
unzip /usr/software/jupyter/e-commerce-customer-behavior-and-sales-analysis-tr.zip -d /Users/kelsen/Code/Jupyter/
1
2
3
4
5
6
7
8
9
10

# 1.2.2 加载数据集

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')

# 设置中文显示(如果需要在图中显示中文)
plt.rcParams['font.sans-serif'] = ['PingFang SC']  # 苹方,macOS默认中文字体
plt.rcParams['axes.unicode_minus'] = False

# 加载数据
df = pd.read_csv('ecommerce_customer_behavior_dataset.csv')  # 文件名根据实际下载情况调整

# 查看数据基本信息
print("数据集形状:", df.shape)
print("\n数据前5行:")
df.head()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 1.2.3 初步探索

# 数据概览
df.info()

# 描述性统计
df.describe(include='all')

# 检查缺失值
print("缺失值统计:")
print(df.isnull().sum())  # 根据数据集说明,应该无缺失值

# 数据类型确认
print("\n数据类型:")
print(df.dtypes)
1
2
3
4
5
6
7
8
9
10
11
12
13

# 1.3 数据清洗与预处理

根据数据集说明,该数据集已经过清洗,无缺失值。但为了教学完整性,我们仍然进行一些必要的预处理。

# 1.3.1 数据类型转换

# 将Date列转换为datetime类型
df['Date'] = pd.to_datetime(df['Date'])

# 将Is_Returning_Customer转换为整数(0/1)
df['Is_Returning_Customer'] = df['Is_Returning_Customer'].astype(int)

# 确认转换后的类型
print(df.dtypes)
1
2
3
4
5
6
7
8

# 1.3.2 添加衍生特征

# 提取时间相关特征
df['Year'] = df['Date'].dt.year
df['Month'] = df['Date'].dt.month
df['Quarter'] = df['Date'].dt.quarter
df['DayOfWeek'] = df['Date'].dt.dayofweek  # 0=周一, 6=周日
df['IsWeekend'] = (df['DayOfWeek'] >= 5).astype(int)

# 计算平均单价(验证Unit_Price * Quantity - Discount = Total_Amount)
df['Calculated_Total'] = df['Unit_Price'] * df['Quantity'] - df['Discount_Amount']
df['Amount_Check'] = np.abs(df['Calculated_Total'] - df['Total_Amount']) < 0.01
print("金额计算验证通过率:", df['Amount_Check'].mean() * 100, "%")

# 计算折扣率
df['Discount_Rate'] = (df['Discount_Amount'] / (df['Unit_Price'] * df['Quantity'])) * 100
# 无折扣的为0
df['Discount_Rate'] = df['Discount_Rate'].fillna(0)

# 创建年龄分组
bins = [0, 25, 35, 45, 55, 100]
labels = ['18-25', '26-35', '36-45', '46-55', '56+']
df['Age_Group'] = pd.cut(df['Age'], bins=bins, labels=labels, right=False)

# 创建评分分组
df['Rating_Group'] = pd.cut(df['Customer_Rating'],
                            bins=[0, 2, 3, 4, 5],
                            labels=['低分(1-2)', '中低分(3)', '中高分(4)', '高分(5)'])

print("衍生特征添加完成")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# 1.3.3 异常值检测

# 使用箱线图检测异常值
fig, axes = plt.subplots(2, 3, figsize=(15, 10))
numeric_cols = ['Age', 'Unit_Price', 'Quantity', 'Total_Amount',
                'Session_Duration_Minutes', 'Delivery_Time_Days']

for i, col in enumerate(numeric_cols):
    row, col_idx = i // 3, i % 3  # 主要是为了拼凑axes[row, col_idx]
    axes[row, col_idx].boxplot(df[col]) # col='Age', ...
    axes[row, col_idx].set_title(f'{col} 箱线图')
    axes[row, col_idx].set_ylabel('值')

plt.tight_layout()
plt.show()

# 使用IQR方法识别异常值
# IQR规则:通常将低于Q1-1.5×IQR或高于Q3+1.5×IQR的值视为异常值。这是统计学中常用的识别离群点的标准
def detect_outliers_iqr(data, column):
    Q1 = data[column].quantile(0.25)
    Q3 = data[column].quantile(0.75)
    IQR = Q3 - Q1
    lower_bound = Q1 - 1.5 * IQR
    upper_bound = Q3 + 1.5 * IQR
    outliers = data[(data[column] < lower_bound) | (data[column] > upper_bound)]
    return outliers, lower_bound, upper_bound

for col in numeric_cols:
    outliers, lb, ub = detect_outliers_iqr(df, col)
    print(f"{col}: 异常值数量 {len(outliers)} ({len(outliers)/len(df)*100:.2f}%)")

# 对于异常值,我们保留但标记
df['Is_High_Value'] = (df['Total_Amount'] > df['Total_Amount'].quantile(0.95)).astype(int)
df['Is_Long_Delivery'] = (df['Delivery_Time_Days'] > df['Delivery_Time_Days'].quantile(0.95)).astype(int)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

# 1.4 探索性数据分析(EDA)

# 1.4.1 整体业务概况

# 关键指标汇总
total_sales = df['Total_Amount'].sum()
total_orders = df['Order_ID'].nunique()
total_customers = df['Customer_ID'].nunique()
avg_order_value = total_sales / total_orders
avg_rating = df['Customer_Rating'].mean()  # 客户评分
returning_rate = df['Is_Returning_Customer'].mean() * 100 #是否回头客

print("="*50)
print("业务概况")
print("="*50)
print(f"总销售额: {total_sales:,.2f} TRY")
print(f"总订单数: {total_orders}")
print(f"总客户数: {total_customers}")
print(f"平均客单价: {avg_order_value:.2f} TRY")
print(f"平均客户评分: {avg_rating:.2f}/5.0")
print(f"回头客比例: {returning_rate:.1f}%")
print(f"移动端交易占比: {(df['Device_Type']=='Mobile').mean()*100:.1f}%")  # 数据集显示约55%
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 1.4.2 销售趋势分析

# 月度销售额趋势
# df['Date'].dt.to_period('M'):将Date列转换为月度周期(例如2023-01),用于按月份分组
# .groupby(...)['Total_Amount'].agg(['sum', 'count', 'mean']):对每个月的Total_Amount列同时计算总和(总销售额)、订单数量(count)和平均值(平均客单价)
monthly_sales = df.groupby(df['Date'].dt.to_period('M'))['Total_Amount'].agg(['sum', 'count', 'mean'])
# 将聚合后的列名改为中文,便于理解
monthly_sales.columns = ['总销售额', '订单数', '平均客单价']
# 索引转换:将月度周期索引(Period类型)转为字符串,便于后续绘图时作为横坐标标签
monthly_sales.index = monthly_sales.index.astype(str)

# 绘制趋势图
fig, axes = plt.subplots(3, 1, figsize=(14, 10))

# 销售额趋势
axes[0].plot(monthly_sales.index, monthly_sales['总销售额'], marker='o', color='blue')
axes[0].set_title('月度销售额趋势 (2023-2024)')
axes[0].set_ylabel('销售额 (TRY)')
axes[0].tick_params(axis='x', rotation=45)

# 订单量趋势
axes[1].plot(monthly_sales.index, monthly_sales['订单数'], marker='s', color='green')
axes[1].set_title('月度订单量趋势')
axes[1].set_ylabel('订单数')
axes[1].tick_params(axis='x', rotation=45)

# 客单价趋势
axes[2].plot(monthly_sales.index, monthly_sales['平均客单价'], marker='^', color='red')
axes[2].set_title('月度平均客单价趋势')
axes[2].set_ylabel('平均客单价 (TRY)')
axes[2].tick_params(axis='x', rotation=45)

plt.tight_layout()
plt.show()

# 识别销售高峰期
# nlargest(3, '总销售额'):从monthly_sales中找出总销售额最高的3个月,并保留这两列(总销售额和订单数)
peak_months = monthly_sales.nlargest(3, '总销售额')[['总销售额', '订单数']]
print("\n销售高峰期TOP3:")
print(peak_months)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

# 1.4.3 客户画像分析

# 性别分布与消费特征
# 按Gender性别分组
# Customer_ID用'nunique'(去重计数):统计不同性别下的独立客户数量(而非订单数)。
# Total_Amount同时计算总和sum和均值mean,得到该性别的总销售额和平均客单价。
# Order_ID用'count':统计该性别下的总订单数。
# Customer_Rating用'mean':计算该性别客户的平均评分。
gender_analysis = df.groupby('Gender').agg({
    'Customer_ID': 'nunique',
    'Total_Amount': ['sum', 'mean'],
    'Order_ID': 'count',
    'Customer_Rating': 'mean'
}).round(2)

# 列重命名:将多级索引简化成直观的中文列名,便于阅读
gender_analysis.columns = ['客户数', '总销售额', '平均客单价', '订单数', '平均评分']
print("性别分析:")
print(gender_analysis)

# 年龄组分析
# 分组键:Age_Group是之前通过分箱创建的年龄段列,如18-25、26-35等。
# observed=True:当分组列为Categorical类型时,此参数确保只显示数据中实际出现的组,而非所有可能的类别(避免出现空组)。如果不设置,可能会显示所有理论分组。
# 聚合指标:与性别分析相同,包括客户数、总销售额、平均客单价、订单数、平均评分。
age_analysis = df.groupby('Age_Group', observed=True).agg({
    'Customer_ID': 'nunique',
    'Total_Amount': ['sum', 'mean'],
    'Order_ID': 'count',
    'Customer_Rating': 'mean'
}).round(2)

age_analysis.columns = ['客户数', '总销售额', '平均客单价', '订单数', '平均评分']
print("\n年龄组分析:")
print(age_analysis)

# 城市分析
# 分组:按City城市分组。
# 聚合指标:总销售额、独立客户数、订单数、平均评分。
# 排序:按总销售额降序排列,便于查看销售表现最好的城市。
city_analysis = df.groupby('City').agg({
    'Total_Amount': 'sum',
    'Customer_ID': 'nunique',
    'Order_ID': 'count',
    'Customer_Rating': 'mean'
}).round(2)

city_analysis.columns = ['总销售额', '客户数', '订单数', '平均评分']
city_analysis = city_analysis.sort_values('总销售额', ascending=False)
print("\n城市销售排行TOP5:")
print(city_analysis.head())
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

# 1.4.4 产品类别分析

# 各类别销售表现
category_analysis = df.groupby('Product_Category').agg({
    'Total_Amount': ['sum', 'mean', 'count'],
    'Quantity': 'sum',
    'Customer_Rating': 'mean',
    'Discount_Amount': 'sum',
    'Is_Returning_Customer': 'mean'
}).round(2)

category_analysis.columns = ['总销售额', '平均客单价', '订单数', '总销量', '平均评分', '折扣总额', '回头客比例']
category_analysis = category_analysis.sort_values('总销售额', ascending=False)

print("产品类别分析:")
print(category_analysis)

# 可视化各类别表现
fig, axes = plt.subplots(2, 2, figsize=(15, 12))

# 销售额占比
axes[0,0].pie(category_analysis['总销售额'], labels=category_analysis.index, autopct='%1.1f%%')
axes[0,0].set_title('各类别销售额占比')

# 平均评分
sns.barplot(x=category_analysis.index, y=category_analysis['平均评分'], ax=axes[0,1])
axes[0,1].set_title('各类别平均评分')
axes[0,1].tick_params(axis='x', rotation=45)

# 订单量
sns.barplot(x=category_analysis.index, y=category_analysis['订单数'], ax=axes[1,0])
axes[1,0].set_title('各类别订单量')
axes[1,0].tick_params(axis='x', rotation=45)

# 平均客单价
sns.barplot(x=category_analysis.index, y=category_analysis['平均客单价'], ax=axes[1,1])
axes[1,1].set_title('各类别平均客单价')
axes[1,1].tick_params(axis='x', rotation=45)

plt.tight_layout()
plt.show()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

# 1.4.5 设备行为分析

# 不同设备的购买行为
device_analysis = df.groupby('Device_Type').agg({
    'Order_ID': 'count',
    'Total_Amount': ['sum', 'mean'],
    'Session_Duration_Minutes': 'mean',
    'Pages_Viewed': 'mean',
    'Customer_Rating': 'mean',
    'Is_Returning_Customer': 'mean'
}).round(2)

device_analysis.columns = ['订单数', '总销售额', '平均客单价', '平均会话时长', '平均浏览页数', '平均评分', '回头客比例']
print("设备类型分析:")
print(device_analysis)

# 设备类型与购买金额关系
fig, axes = plt.subplots(1, 3, figsize=(15, 5))

sns.boxplot(data=df, x='Device_Type', y='Total_Amount', ax=axes[0])
axes[0].set_title('不同设备的客单价分布')

sns.boxplot(data=df, x='Device_Type', y='Session_Duration_Minutes', ax=axes[1])
axes[1].set_title('不同设备的会话时长分布')

sns.boxplot(data=df, x='Device_Type', y='Pages_Viewed', ax=axes[2])
axes[2].set_title('不同设备的浏览页数分布')

plt.tight_layout()
plt.show()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# 1.4.6 客户忠诚度分析

# 回头客vs新客户
loyalty_analysis = df.groupby('Is_Returning_Customer').agg({
    'Order_ID': 'count',
    'Total_Amount': ['sum', 'mean'],
    'Customer_Rating': 'mean',
    'Session_Duration_Minutes': 'mean',
    'Pages_Viewed': 'mean',
    'Delivery_Time_Days': 'mean'
}).round(2)

loyalty_analysis.columns = ['订单数', '总销售额', '平均客单价', '平均评分', '平均会话时长', '平均浏览页数', '平均配送时间']
loyalty_analysis.index = ['新客户', '回头客']

print("客户忠诚度分析:")
print(loyalty_analysis)

# 客户购买频次分布
customer_frequency = df.groupby('Customer_ID')['Order_ID'].count().reset_index()
customer_frequency.columns = ['Customer_ID', 'Purchase_Count']

fig, axes = plt.subplots(1, 2, figsize=(14, 5))

# 购买频次分布
sns.histplot(customer_frequency['Purchase_Count'], bins=20, kde=True, ax=axes[0])
axes[0].set_title('客户购买频次分布')
axes[0].set_xlabel('购买次数')
axes[0].set_ylabel('客户数')

# 帕累托分析(累计销售额贡献)
customer_value = df.groupby('Customer_ID')['Total_Amount'].sum().sort_values(ascending=False).reset_index()
customer_value['Cumulative_Pct'] = customer_value['Total_Amount'].cumsum() / customer_value['Total_Amount'].sum() * 100

axes[1].plot(range(1, len(customer_value)+1), customer_value['Cumulative_Pct'])
axes[1].axhline(y=80, color='r', linestyle='--', label='80% 销售额')
axes[1].axvline(x=len(customer_value)*0.2, color='g', linestyle='--', label='20% 客户')
axes[1].set_title('帕累托分析:客户累计销售额贡献')
axes[1].set_xlabel('客户数(按价值排序)')
axes[1].set_ylabel('累计销售额占比 (%)')
axes[1].legend()

plt.tight_layout()
plt.show()

# 计算前20%客户贡献的销售额比例
top_20_pct = int(len(customer_value) * 0.2)
top_20_contribution = customer_value.iloc[:top_20_pct]['Total_Amount'].sum() / customer_value['Total_Amount'].sum() * 100
print(f"前20%的客户贡献了 {top_20_contribution:.1f}% 的销售额")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

# 1.4.7 配送时间与客户满意度

# 配送时间分析
delivery_analysis = df.groupby('Delivery_Time_Days').agg({
    'Customer_Rating': 'mean',
    'Order_ID': 'count'
}).reset_index()

fig, axes = plt.subplots(1, 2, figsize=(14, 5))

# 配送时间分布
sns.histplot(df['Delivery_Time_Days'], bins=30, kde=True, ax=axes[0])
axes[0].set_title('配送时间分布')
axes[0].set_xlabel('配送天数')
axes[0].set_ylabel('订单数')

# 配送时间与评分关系
sns.scatterplot(data=delivery_analysis, x='Delivery_Time_Days', y='Customer_Rating',
                size='Order_ID', sizes=(20, 200), ax=axes[1])
axes[1].set_title('配送时间 vs 客户评分')
axes[1].set_xlabel('配送天数')
axes[1].set_ylabel('平均客户评分')

plt.tight_layout()
plt.show()

# 计算相关性
correlation = df['Delivery_Time_Days'].corr(df['Customer_Rating'])
print(f"配送时间与客户评分的相关系数: {correlation:.3f}")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# 1.5 高级分析与可视化

# 1.5.1 相关性热力图

# 选择数值列进行相关性分析
numeric_df = df[['Age', 'Unit_Price', 'Quantity', 'Total_Amount', 'Discount_Amount',
                 'Session_Duration_Minutes', 'Pages_Viewed', 'Is_Returning_Customer',
                 'Delivery_Time_Days', 'Customer_Rating']]

correlation_matrix = numeric_df.corr()

plt.figure(figsize=(12, 10))
sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', center=0,
            square=True, linewidths=1, cbar_kws={"shrink": 0.8})
plt.title('数值特征相关性热力图')
plt.tight_layout()
plt.show()
1
2
3
4
5
6
7
8
9
10
11
12
13

# 1.5.2 使用Pyecharts创建交互式仪表板

from pyecharts.charts import Bar, Line, Pie, Scatter, Grid, Page
from pyecharts import options as opts
from pyecharts.globals import ThemeType

# 准备数据
monthly_data = monthly_sales.reset_index()
# 动态获取索引列名
index_col_name = monthly_data.columns[0]
months = monthly_data[index_col_name].tolist()
sales_values = monthly_data['总销售额'].tolist()
order_values = monthly_data['订单数'].tolist()

# 1. 月度销售额折线图
line_chart = (
    Line()
    .add_xaxis(months)
    .add_yaxis("销售额", sales_values, is_smooth=True, color="#5470C6")
    .set_global_opts(
        title_opts=opts.TitleOpts(title="月度销售额趋势"),
        tooltip_opts=opts.TooltipOpts(trigger="axis"),
        xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=45)),
        yaxis_opts=opts.AxisOpts(name="销售额 (TRY)"),
        legend_opts=opts.LegendOpts(pos_left="center")
    )
)

# 2. 类别销售额柱状图
category_data = category_analysis.reset_index()
categories = category_data['Product_Category'].tolist()
category_sales = category_data['总销售额'].tolist()

bar_chart = (
    Bar()
    .add_xaxis(categories)
    .add_yaxis("销售额", category_sales, color="#91CC75")
    .set_global_opts(
        title_opts=opts.TitleOpts(title="各类别销售额"),
        xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=45)),
        yaxis_opts=opts.AxisOpts(name="销售额")
    )
    .set_series_opts(label_opts=opts.LabelOpts(is_show=True))
)

# 3. 支付方式饼图
payment_counts = df['Payment_Method'].value_counts()
payment_data = [(k, v) for k, v in payment_counts.items()]

pie_chart = (
    Pie()
    .add("", payment_data, radius=["40%", "70%"])
    .set_global_opts(
        title_opts=opts.TitleOpts(title="支付方式分布"),
        legend_opts=opts.LegendOpts(orient="vertical", pos_top="15%", pos_left="2%")
    )
    .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {d}%"))
)

# 4. 设备类型与客单价散点图
device_sample = df.sample(min(500, len(df)))
device_scatter = (
    Scatter()
    .add_xaxis(device_sample['Device_Type'].tolist())
    .add_yaxis("客单价", device_sample['Total_Amount'].tolist(),
               label_opts=opts.LabelOpts(is_show=False))
    .set_global_opts(
        title_opts=opts.TitleOpts(title="不同设备客单价分布"),
        xaxis_opts=opts.AxisOpts(name="设备类型"),
        yaxis_opts=opts.AxisOpts(name="客单价")
    )
)

# 在Jupyter中显示
line_chart.render_notebook()
bar_chart.render_notebook()
pie_chart.render_notebook()
device_scatter.render_notebook()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

# 1.5.3 客户分群(K-Means聚类)

根据客户消费行为进行分群,这是电商分析中常用的技术。

from sklearn.preprocessing import StandardScaler
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA

# 准备客户级别特征
customer_features = df.groupby('Customer_ID').agg({
    'Total_Amount': ['sum', 'mean'],
    'Order_ID': 'count',
    'Customer_Rating': 'mean',
    'Session_Duration_Minutes': 'mean',
    'Pages_Viewed': 'mean',
    'Delivery_Time_Days': 'mean',
    'Discount_Rate': 'mean'
}).round(2)

# 扁平化列名
customer_features.columns = ['总消费额', '平均客单价', '购买次数',
                             '平均评分', '平均会话时长', '平均浏览页数',
                             '平均配送时间', '平均折扣率']

# 重置索引使Customer_ID成为列
customer_features = customer_features.reset_index()

# 标准化特征
scaler = StandardScaler()
features_for_clustering = ['总消费额', '购买次数', '平均客单价', '平均评分']
scaled_features = scaler.fit_transform(customer_features[features_for_clustering])

# 使用肘部法则确定最佳聚类数
inertias = []
K_range = range(2, 9)

for k in K_range:
    kmeans = KMeans(n_clusters=k, random_state=42, n_init=10)
    kmeans.fit(scaled_features)
    inertias.append(kmeans.inertia_)

# 绘制肘部图
plt.figure(figsize=(10, 6))
plt.plot(K_range, inertias, 'bo-')
plt.xlabel('聚类数 K')
plt.ylabel('惯性 (Inertia)')
plt.title('肘部法则确定最佳K值')
plt.grid(True)
plt.show()

# 选择K=4进行聚类
kmeans = KMeans(n_clusters=4, random_state=42, n_init=10)
customer_features['Cluster'] = kmeans.fit_predict(scaled_features)

# 分析各簇特征
cluster_analysis = customer_features.groupby('Cluster')[features_for_clustering].mean()
print("各客户群特征:")
print(cluster_analysis)

# 使用PCA降维可视化
pca = PCA(n_components=2)
pca_result = pca.fit_transform(scaled_features)

plt.figure(figsize=(12, 8))
scatter = plt.scatter(pca_result[:, 0], pca_result[:, 1],
                     c=customer_features['Cluster'], cmap='viridis', alpha=0.6)
plt.colorbar(scatter, label='聚类')
plt.xlabel('第一主成分')
plt.ylabel('第二主成分')
plt.title('客户聚类可视化 (PCA降维)')
plt.show()

# 为各簇命名
cluster_names = {
    0: '高价值忠诚客户',
    1: '普通大众客户',
    2: '潜力新客户',
    3: '低价值客户'
}
customer_features['Cluster_Name'] = customer_features['Cluster'].map(cluster_names)

# 各簇占比
cluster_distribution = customer_features['Cluster_Name'].value_counts()
print("\n各客户群占比:")
print(cluster_distribution)
print(cluster_distribution / len(customer_features) * 100)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82

# 1.5.4 评分预测建模(基础机器学习)

from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error, r2_score, mean_absolute_error

# 准备特征和目标变量
feature_cols = ['Age', 'Unit_Price', 'Quantity', 'Discount_Rate',
                'Session_Duration_Minutes', 'Pages_Viewed', 'Is_Returning_Customer',
                'Delivery_Time_Days']
target_col = 'Customer_Rating'

# 对分类变量进行独热编码
df_encoded = pd.get_dummies(df, columns=['Gender', 'Product_Category',
                                          'Payment_Method', 'Device_Type'])

# 选择特征列,原来是数字的8列 加上刚刚独热编码的列,组合在一起为X
X = df_encoded[feature_cols + [col for col in df_encoded.columns if col.startswith(('Gender_', 'Product_Category_', 'Payment_Method_', 'Device_Type_'))]]
y = df_encoded[target_col]

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 训练随机森林模型
rf_model = RandomForestRegressor(n_estimators=100, max_depth=10, random_state=42)
rf_model.fit(X_train, y_train)

# 预测
y_pred = rf_model.predict(X_test)

# 评估
mse = mean_squared_error(y_test, y_pred)
mae = mean_absolute_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)

print("模型评估结果:")
print(f"均方误差 (MSE): {mse:.4f}")
print(f"平均绝对误差 (MAE): {mae:.4f}")
print(f"R² 分数: {r2:.4f}")

# 特征重要性
feature_importance = pd.DataFrame({
    'feature': X.columns,
    'importance': rf_model.feature_importances_
}).sort_values('importance', ascending=False)

print("\n特征重要性TOP10:")
print(feature_importance.head(10))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

# 1.6 结论与商业建议

# 1.6.1 关键发现总结

# 汇总关键指标
insights = {
    "客户概况": {
        "回头客比例": f"{returning_rate:.1f}%",
        "移动端占比": f"{(df['Device_Type']=='Mobile').mean()*100:.1f}%",
        "平均客单价": f"{avg_order_value:.2f} TRY",
        "平均评分": f"{avg_rating:.2f}/5.0"
    },
    "销售表现": {
        "总销售额": f"{total_sales:,.2f} TRY",
        "总订单数": f"{total_orders}",
        "高峰期": f"{peak_months.index[0]} (销售额{peak_months.iloc[0]['总销售额']:,.0f} TRY)"
    },
    "产品表现": {
        "最畅销类别": category_analysis.index[0],
        "评分最高类别": category_analysis['平均评分'].idxmax(),
        "客单价最高类别": category_analysis['平均客单价'].idxmax()
    }
}

print("\n" + "="*60)
print("关键发现总结")
print("="*60)

for category, metrics in insights.items():
    print(f"\n{category}:")
    for key, value in metrics.items():
        print(f"  - {key}: {value}")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# 1.6.2 商业建议

基于以上分析,提出以下商业建议:

recommendations = [
    {
        "领域": "客户细分与精准营销",
        "发现": f"前20%的客户贡献了{top_20_contribution:.1f}%的销售额,符合帕累托法则",
        "建议": "针对高价值客户(聚类中的0簇)建立VIP计划,提供专属优惠和快速配送;针对潜力客户(2簇)推送个性化推荐,提升转化率"
    },
    {
        "领域": "产品策略优化",
        "发现": f"{category_analysis.index[0]}类别销售额最高,但评分最高的类别是{category_analysis['平均评分'].idxmax()}",
        "建议": "保持{category_analysis.index[0]}类别的库存充足,同时分析{category_analysis['平均评分'].idxmax()}类别的成功因素,应用到其他类别"
    },
    {
        "领域": "移动端体验优化",
        "发现": f"移动端交易占比{(df['Device_Type']=='Mobile').mean()*100:.1f}%,但平均客单价低于桌面端",
        "建议": "优化移动端购物流程,简化支付步骤,考虑推出移动端专属优惠"
    },
    {
        "领域": "配送服务改进",
        "发现": f"配送时间与客户评分相关系数为{correlation:.3f},呈负相关",
        "建议": "对配送时间超过7天的订单主动跟踪并提供补偿;考虑在高峰期增加配送人力"
    },
    {
        "领域": "客户忠诚度提升",
        "发现": f"回头客比例{returning_rate:.1f}%,且回头客的客单价和评分均高于新客户",
        "建议": "实施会员积分制度,对重复购买客户提供累计折扣;定期发送个性化推荐邮件"
    }
]

print("\n" + "="*60)
print("商业建议")
print("="*60)

for i, rec in enumerate(recommendations, 1):
    print(f"\n{i}. {rec['领域']}")
    print(f"   📊 发现: {rec['发现']}")
    print(f"   💡 建议: {rec['建议']}")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

# 1.6.3 未来研究方向

future_work = [
    "时间序列预测:使用ARIMA或Prophet模型预测未来销售趋势",
    "推荐系统:基于用户购买历史构建协同过滤推荐引擎",
    "客户生命周期价值(CLV)预测:预估客户长期价值,优化营销预算分配",
    "A/B测试框架:设计实验验证营销策略的有效性",
    "自然语言处理:如果获取到评论数据,可进行情感分析"
]

print("\n" + "="*60)
print("未来研究方向")
print("="*60)
for item in future_work:
    print(f"  • {item}")
1
2
3
4
5
6
7
8
9
10
11
12
13

# 1.7 代码完整性与可复现性

为确保分析的可复现性,建议将所有代码整合到一个Jupyter Notebook中,并包含以下设置:

# 环境配置和依赖
import sys
print("Python版本:", sys.version)
print("Pandas版本:", pd.__version__)
print("NumPy版本:", np.__version__)
print("Matplotlib版本:", plt.matplotlib.__version__)
print("Seaborn版本:", sns.__version__)

# 如果需要保存处理后的数据
df.to_csv('processed_ecommerce_data.csv', index=False)
customer_features.to_csv('customer_segments.csv', index=False)

# 保存可视化图表
plt.savefig('sales_trend.png', dpi=300, bbox_inches='tight')
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 1.8 案例总结

本案例基于Kaggle平台的真实电商数据集,完整演示了数据分析的全流程:

  1. 数据获取:使用Kaggle API下载真实数据集
  2. 数据清洗:处理数据类型、添加衍生特征、检测异常值
  3. 探索性分析:从客户画像、产品表现、设备行为、客户忠诚度等多个维度深入分析
  4. 高级分析:相关性分析、客户聚类分群、基础预测建模
  5. 可视化呈现:综合使用Matplotlib、Seaborn和Pyecharts创建静态与交互式图表
  6. 商业洞察:基于数据得出actionable的商业建议

通过本案例,读者可以掌握处理真实数据集的能力,理解如何将数据分析技术应用于实际业务场景,并能够从数据中提炼有价值的商业洞察。

明天Day6见!See you tomorrow!

最近更新: 2026/9/30
 |  Copyright © -Present Kelsen All Rights Reserved. | Author KelsenJing