数据分析 — 电商用户分析和用户 RFM 模型

一、电商用户分析

1、数据字段信息

字段 说明
RowID 行编号
OrderID 订单 ID
OrderDate 订单日期
ShipDate 发货日期
ShipMode 发货模式
CustomerID 客户 ID
CustomerName 客户姓名
Segment 客户类别
City 客户所在城市
State 客户所在州
Country 客户所在国家
PostalCode 邮编
Market 商店所属区域
Region 商店所属州
ProductID 产品 ID
Category 产品类别
Sub-Category 产品子类别
ProductName 产品名称
Sales 售价
Quantity 销售量
Discount 折扣
Profit 利润
ShippingCost 发货成本
OrderPriority 订单优先级

2、数据读取

import pandas as pd  # 导入 Pandas 库并使用别名 pd
# 读取 CSV 文件,使用 gbk 编码
data = pd.read_csv(r'F:\data\dataset.csv', encoding='gbk')
print(data)

在这里插入图片描述

# 打印数据的列名
print(data.columns)

在这里插入图片描述

# 重新命名数据的列名
data.columns = ['行编号', '订单ID', '订单日期', '发货日期', '发货模式', '客户ID', '客户姓名', '客户类别', '客户所在城市', '客户所在州', '客户所在国家', '邮编', '商店所属区域', '商店所属州', '产品ID', '产品类别', '产品子类别', '产品名称', '售价', '销售量', '折扣', '利润', '发货成本', '订单优先级']
print(data.head())

在这里插入图片描述

3、数据清洗

在这里插入图片描述

# 打印数据的基本信息
data.info()

在这里插入图片描述

# 1、发货日期 - 订单日期 >= 0,异常的数据 < 0
# 将 '发货日期' 和 '订单日期' 列的数据类型转换为 datetime
data['发货日期'] = pd.to_datetime(data['发货日期'])
data['订单日期'] = pd.to_datetime(data['订单日期'])
# 计算 '发货秒数' 列,表示发货日期与订单日期的时间差(秒)
data['发货秒数'] = (data['发货日期'] - data['订单日期']).dt.total_seconds()

# 删除发货日期早于订单日期的
data.drop(index=data[data['发货秒数'] < 0].index, inplace=True)  # drop() 这里是按索引删除
print(data.head())

在这里插入图片描述

# 打印数据的形状
print(data.shape)  # (51097, 25)
# 2、删除售价为负数据(异常数据)
# 查找 '售价' 列小于 0 的行
print(data[data['售价'] < 0])
# 没有售价为负的,不用处理

在这里插入图片描述

# 打印数据的信息
data.info()

在这里插入图片描述

# 3、查看空值,重复值
# 打印每列的缺失值数量
print(data.isnull().sum())

在这里插入图片描述

# 计算 '行编号' 列的唯一值数量
print(data['行编号'].unique().size)  # 51094
# 删除重复的 '行编号' 行(去重)
data.drop_duplicates('行编号', inplace=True)
data.info()

在这里插入图片描述

# 清洗 '发货模式' 
# 打印 '发货模式' 列的缺失值数量
print(data['发货模式'].isnull().sum())  # 11
# 打印 '发货模式' 列的众数(出现次数最多的)
print(data['发货模式'].mode())
# 0    Standard Class
# dtype: object
# 打印 '发货模式' 列的类型
print(type(data['发货模式'].mode()))
# <class 'pandas.core.series.Series'>

# 用众数填充 '发货模式' 列的缺失值
data['发货模式'].fillna(value=data['发货模式'].mode()[0], inplace=True)
# 打印 '发货模式' 列的缺失值数量
print(data['发货模式'].isnull().sum())  # 0
# 删除 '邮编' 列(缺失多且对本次分析无用)
data.drop(columns=['邮编'], inplace=True)
data.info()

在这里插入图片描述

# 打印数据的描述统计信息
print(data.describe())

在这里插入图片描述

# 清洗 '折扣' 
# 查找 '折扣' 列大于 1 的行
print(data[data['折扣'] > 1])

在这里插入图片描述

# 将 '折扣' 列大于 1 的值替换为 None
data['折扣'] = data['折扣'].mask(data['折扣'] > 1, None)
# 用 '折扣' 列的均值填充缺失值
data['折扣'].fillna(value=round(data['折扣'].mean(), 2), inplace=True)
# 打印数据的描述统计信息
print(data.describe())

在这里插入图片描述

# 清洗 '订单日期'
# 添加 '下订单年'、'下订单月' 和 '下订单季度' 列
data['下订单年'] = data['订单日期'].dt.year
data['下订单月'] = data['订单日期'].dt.month
data['下订单季度'] = data['订单日期'].dt.to_period('Q')
print(data.head())

在这里插入图片描述

# 查找重复的行数
print(data.duplicated().sum())  # 0

4、可视化分析

1、每年销售额的增长情况

# 创建一个新的列'销售额',计算售价与销售量的乘积,表示销售额
data['销售额'] = data['售价']*data['销售量']
# 打印数据的前几行,用于查看新增的销售额列
print(data.head())

在这里插入图片描述

# 根据'下订单年'列分组,计算每年的销售额总和
sales_year = data.groupby('下订单年')['销售额'].sum()
# 打印每年的销售额总和
print(sales_year)
# 下订单年
# 2011    1.110551e+07
# 2012    1.290868e+07
# 2013    1.667801e+07
# 2014    2.090141e+07
# Name: 销售额, dtype: float64
# 计算每年的销售额增长率,分别以2012年、2013年、2014年为基准年
sales_year_12 = (sales_year[2012]/sales_year[2011]) -1
sales_year_13 = (sales_year[2013]/sales_year[2012]) -1
sales_year_14 = (sales_year[2014]/sales_year[2013]) -1
# 打印销售额增长率
print(sales_year_12, sales_year_13, sales_year_14)
# 0.16236705386979122 0.29200004761249243 0.2532315853953533
# 创建一个包含年销售额和订单增长率的数据框
sales_rate = pd.DataFrame({
   
    '年销售额':sales_year,
    '订单增长率':[0, sales_year_12, sales_year_13, sales_year_14]
})
# 打印包含销售额和增长率的数据框
print(sales_rate)

在这里插入图片描述

import matplotlib.pyplot as plt  # 导入 Matplotlib 库
# 设置字体为中文黑体
plt.rcParams['font.family'] = 'SimSun'

# 准备绘图所需的数据
x = [str(value) for value in sales_rate.index.tolist()]  # 把数值转成字符串
# 两个 y 轴数据差距很大,但又要画在同一个图里.可以使用双 y 轴
y1 = sales_rate['年销售额']
y2 = sales_rate['订单增长率']

# 创建一个包含两个子图的图表,并设置图表大小
fig = plt.figure(figsize=(10,6))
# 新建子图1 
ax1 = fig.add_subplot(1,1,1)
# ax2 与 ax1 共享 x 轴
ax2 = ax1.twinx()

# 绘制柱状图表示年销售额
ax1.bar(x, y1, color='blue', label='年销售额')

# 绘制折线图表示年增长率
ax2.plot(x, y2, marker='*', color='r', linewidth=3, markersize='10', label='年增长率')

# 添加x轴标签
ax1.set_xlabel('年份', fontsize=20)
ax1.set_ylabel('年销售额', fontsize=20)
ax2.set_ylabel('年增长率', fontsize=20)

# 设置刻度 
ax1.tick_params(axis='x', labelsize=15)
ax1.tick_params(axis='y', labelsize=15)
ax2.tick_params(axis='y', labelsize=15)

# 设置图例位置和外边界框
ax1.legend(loc='upper right', bbox_to_anchor=(1.25, 1))
ax2.legend(loc='upper right', bbox_to_anchor=(1.25, 1.08))

# 显示图表
plt.show()

在这里插入图片描述

结论:

年销售额逐年递增。

2、各个地区分店的销售额

# 打印数据的前几行,用于查看数据的整体情况
print(data.head())

在这里插入图片描述

# 打印数据的基本信息,包括列的数据类型和非空值数量
data.info()

在这里插入图片描述

# 根据'商店所属区域'列分组,计算各区域的销售额总和
sales_area = data.groupby('商店所属区域')['销售额'].sum()
# 打印各区域的销售额总和
print(sales_area)

在这里插入图片描述

# 绘制销售额占比的饼图,以百分比形式显示,设置标题和字体大小,以及图表大小
sales_area.plot(kind='pie', autopct='%1.1f%%', title='2011年-2014各分店销售额占比', fontsize=15, figsize=(10,10))
# 显示图表
plt.show()

在这里插入图片描述

结论:

APAC 分店销售额占比最高,近1/3。

3、每个分店每一年的销售额

# 打印数据的基本信息,包括列的数据类型和非空值数量
data.info()

在这里插入图片描述

# 使用数据透视表,根据'商店所属区域'和'下订单年',计算不同地区每年的销售额总和
sales_area2 = pd.pivot_table(data, index='商店所属区域', columns='下订单年', values='销售额', aggfunc='sum')
# 打印不同地区每年销售额的数据透视表
print(sales_area2)

在这里插入图片描述

# 绘制柱状图,对比2011年-2014年不同地区每年的销售额
sales_area2.plot(kind='bar', title='2011年-2014年不同地区每年销售额对比', figsize=(10, 6), fontsize=15)
# 显示图表
plt.show()

在这里插入图片描述

结论:

销售额逐年增长。

4、销售淡旺季

# 使用数据透视表,根据'下订单月'和'下订单年',计算每年每月的销售额总和
sales_year_month = pd.pivot_table(data, index='下订单月', columns='下订单年', values='销售额', aggfunc='sum')
# 打印每年每月销售额的数据透视表
print(sales_year_month)

在这里插入图片描述

# 绘制折线图,显示每年每月的销售额趋势,并添加图例
sales_year_month.plot(fontsize=15, figsize=(10, 6)).legend(fontsize=15)
# 显示图表
plt.show()

在这里插入图片描述

结论:

旺季 6月和11月,淡季 2月 4月 7月。

5、新增用户

# 求每年每月的新增用户数
# 复制原始数据,以便后续分析客户相关信息
data_customer = data.copy()
# print(data_customer)

# 新用户,第一次购买,对用户进行去重
# 根据'客户ID'去重,保留第一次出现的记录
data_customer = data_customer.drop_duplicates(subset='客户ID')
# print(data_customer)

# 按年按月分组聚合
# 使用数据透视表,根据'下订单月'和'下订单年',计算每年每月不同客户的数量
customer_year_month = pd.pivot_table(data_customer, index='下订单月', columns='下订单年', values='客户ID', fill_value=0, aggfunc='count')
# 打印每年每月不同客户的数量的数据透视表
print(customer_year_month)

在这里插入图片描述

二、RFM 模型

1、RFM 模型的三个维度

Recency(最近购买时间):

这个维度衡量客户最近一次购买的时间,通常以天数来表示。较短的 Recency 值表示客户最近有过购买行为,而较⻓的 Recency 值则表示客户离上次购买较远。Recency 的分析有助于识别哪些客户是“活跃客户”。

Frequency(购买频率):

这个维度衡量客户在一定时间内的购买次数。购买频率高的客户可能更容易进行再营销活动,因为他们已经展现出对产品或服务的兴趣和忠诚度。

Monetary(购买金额):

这个维度衡量客户在一定时间内的总购买金额。购买金额高的客户可能是企业的高价值客户,因此在市场营销活动中可能需要特别关注和激励这一群体。

2、RFM 的客户类型标签

R F M 客户类型
0 1 1 重要价值客户
1 1 1 重要唤回客户
0 0 1 重要深耕客户
1 0 1 重要挽留客户
0 1 0 潜力客户
1 1 0 一般维持客户
0 0 0 新客户
1 0 0 流失客户

3、RFM 模型的二分法思想

Recency(最近购买时间):

  • R1:最近购买时间较短的客户
  • R2:最近购买时间较⻓的客户

Frequency(购买频率):

  • F1:购买频率较高的客户
  • F2:购买频率较低的客户

Monetary(购买金额):

  • M1:购买金额较高的客户
  • M2:购买金额较低的客户

界定某一数据被分在哪个区间,这里采用平均值来实现,即大于平均值,被分为一类,小于平均值被分为另一类。至于等于平均值,被归于哪一类,实际归到哪一类都可以,只需保证所有数据使用相同的规则即可。

4、代码

# 打印数据集的形状
print(data.shape)  # (51094, 28)
# 输出数据集的信息
data.info()

在这里插入图片描述

# 筛选出 '下订单年' 列为 2014 年的数据
data_14 = data[data['下订单年'] == 2014]
# 打印筛选后的数据集
print(data_14)

在这里插入图片描述

# 复制筛选后的数据集
customerdf = data_14.copy()
# 打印复制后的数据集
print(customerdf)

在这里插入图片描述

# 在复制的数据集中新增一列 '订单数',并将其初始化为 1
customerdf['订单数'] = 1
# 打印修改后的数据集的前几行
print(customerdf.head())

在这里插入图片描述

# 使用 pivot_table 计算 RFM 指标,包括最近购买日期、总订单数和总销售额
rfmdf = customerdf.pivot_table(index='客户ID',
                               values=['订单日期', '订单数', '销售额'],
                               aggfunc={
   '订单日期': 'max', '订单数': 'sum', '销售额': 'sum'})
# 打印 RFM 指标表
print(rfmdf)

在这里插入图片描述

# 计算最近购买日期距离当前日期的天数,添加一列 'R'
# 把所有交易记录数据里最晚的交易时间看成是现在当前时间
rfmdf['R'] = (rfmdf['订单日期'].max() - rfmdf['订单日期']).dt.days
# 打印添加 'R' 列后的 RFM 指标表
print(rfmdf)

在这里插入图片描述

# 重命名列名为 'R'、'F' 和 'M'
rfmdf.rename(columns={
   '订单数': 'F', '销售额': 'M'}, inplace=True)
# 打印重命名后的 RFM 指标表
print(rfmdf)

在这里插入图片描述

# 仅保留 'R'、'F'、'M' 列
rfmdf = rfmdf[['R', 'F', 'M']]
# 打印最终的 RFM 指标表
print(rfmdf)

在这里插入图片描述

# 定义函数 rfm_func,根据 RFM 的值给客户打标签,并创建新列 '用户标签'
def rfm_func(x):
    level = x.apply(lambda x: '1' if x > 0 else '0')
    label = level['R'] + level['F'] + level['M']
    d = {
   
        '011': '重要价值客户',
        '111': '重要唤回客户',
        '001': '重要深耕客户',
        '101': '重要挽留客户',
        '010': '潜力客户',
        '110': '一般维持客户',
        '000': '新客户',
        '100': '流失客户'
    }
    return d[label]
# 应用 rfm_func 函数,创建 '用户标签' 列
rfmdf['用户标签'] = rfmdf.apply(lambda x: x - x.mean()).apply(rfm_func, axis=1)
# 打印添加 '用户标签' 列后的 RFM 指标表
print(rfmdf)

在这里插入图片描述

import matplotlib.pyplot as plt  # 导入 Matplotlib 库
# 设置字体为中文黑体
plt.rcParams['font.family'] = 'SimSun'
plt.style.use('fivethirtyeight')
rfmdf['用户标签'].value_counts().plot.bar(figsize=(20, 9), fontsize=15)
plt.show()

在这里插入图片描述

记录学习过程,欢迎讨论交流,尊重原创,转载请注明出处~

相关推荐

  1. 用户行为数据分析

    2024-02-21 09:48:03       39 阅读
  2. 数据分析——分群思维、RFM实现用户分群

    2024-02-21 09:48:03       30 阅读
  3. 基于 Spark 的用户行为分析系统

    2024-02-21 09:48:03       35 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-02-21 09:48:03       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-02-21 09:48:03       100 阅读
  3. 在Django里面运行非项目文件

    2024-02-21 09:48:03       82 阅读
  4. Python语言-面向对象

    2024-02-21 09:48:03       91 阅读

热门阅读

  1. Android为现有的应用工程设置 Compose

    2024-02-21 09:48:03       53 阅读
  2. 【数据结构——顺序表三种数据结构差异】

    2024-02-21 09:48:03       56 阅读
  3. zookeeper动态扩缩容(无需重启)

    2024-02-21 09:48:03       42 阅读
  4. 物联网平台构成与边缘计算

    2024-02-21 09:48:03       50 阅读
  5. 从查字典到查网络再到查大语言模型

    2024-02-21 09:48:03       52 阅读
  6. 单精度(float)和双精度(double)的区别

    2024-02-21 09:48:03       54 阅读