使用 K-Means 进行客户分群分析

使用 K-Means 进行客户分群分析

本文将详细介绍如何使用 K-Means 聚类算法对客户的购买行为进行分群分析。我们会从数据清理和特征工程开始,到 K-Means 聚类的应用,最后进行结果的分析和商业洞察。使用的数据集为 Online Retail 数据集,包含了一家在线零售商的交易数据。

数据集概述

Online Retail 数据集包含了详细的交易信息,字段包括:

  • InvoiceNo: 每笔交易的唯一发票编号。如果发票编号以 “C” 开头,则表示该交易为退货记录。
  • StockCode: 唯一标识每种产品的代码。
  • Description: 产品的描述信息。
  • Quantity: 每笔交易中购买的产品数量。
  • InvoiceDate: 交易的日期和时间。
  • UnitPrice: 单价(英镑)。
  • CustomerID: 客户的唯一标识符。
  • Country: 客户所在国家。
数据清理与预处理

为了确保数据的准确性和完整性,首先对数据进行了必要的清理和预处理,具体步骤如下:

  1. 去除缺失的 CustomerID 数据: 数据集中有些交易记录缺少客户编号,这些记录无法关联到具体的客户,因此需要删除。
  2. 删除退货订单及交易金额小于 0 的记录: 退货订单通过 InvoiceNo 以 “C” 开头进行识别,因为这些记录不反映正常的购买行为,所以删除。同时删除交易金额小于 0 的异常记录。
  3. 计算总消费金额 (TotalPrice): 新增 TotalPrice 列,用于表示每笔交易的总金额,计算方式为 Quantity * UnitPrice

以下是数据清理的代码实现:

import pandas as pd

# 读取数据集
file_path = 'Online Retail.xlsx'
data = pd.read_excel(file_path)

# 数据清理
# 去除缺失的 CustomerID 行
data_cleaned = data.dropna(subset=['CustomerID'])

# 将 InvoiceNo 转为字符串类型
data_cleaned['InvoiceNo'] = data_cleaned['InvoiceNo'].astype(str)

# 删除退货订单及交易金额小于 0 的记录
data_cleaned = data_cleaned[~data_cleaned['InvoiceNo'].str.startswith('C')]
data_cleaned = data_cleaned[data_cleaned['Quantity'] > 0]
data_cleaned = data_cleaned[data_cleaned['UnitPrice'] > 0]

# 计算总消费金额
data_cleaned['TotalPrice'] = data_cleaned['Quantity'] * data_cleaned['UnitPrice']
特征工程

在数据清理完成后,我们进行了特征工程,提取了一些反映客户购买行为的特征,这些特征用于后续的聚类分析,包括:

  • TotalQuantity: 客户的总购买数量。
  • TotalPrice: 客户的总消费金额。
  • MaxQuantity: 客户单次购买的最大数量。
  • MaxPrice: 客户购买的最高单价。
  • AvgQuantity: 客户的平均购买数量。
  • AvgPrice: 客户的平均购买价格。

以下是特征提取的代码:

# 特征工程
customer_data = data_cleaned.groupby('CustomerID').agg(
    TotalQuantity=('Quantity', 'sum'),
    TotalPrice=('TotalPrice', 'sum'),
    MaxQuantity=('Quantity', 'max'),
    MaxPrice=('UnitPrice', 'max'),
    AvgQuantity=('Quantity', 'mean'),
    AvgPrice=('UnitPrice', 'mean')
).reset_index()
数据标准化

由于不同特征的量级差异较大,例如总消费金额和平均购买数量,这些特征直接用于聚类会导致结果不一致。因此,我们使用 StandardScaler 对数据进行了标准化处理,使得各特征在相同的尺度下进行比较。

from sklearn.preprocessing import StandardScaler

# 数据标准化
scaler = StandardScaler()
scaled_customer_data = scaler.fit_transform(customer_data[['TotalQuantity', 'TotalPrice', 'MaxQuantity', 'MaxPrice', 'AvgQuantity', 'AvgPrice']])
使用肘部法确定最佳 K 值

为了确定 K-Means 聚类的最佳簇数量 ( K ),我们采用了肘部法。肘部法通过绘制簇内误差平方和(Inertia)与簇数量之间的关系图,来判断最佳的聚类数量。曲线在某点出现明显弯曲时,即为“肘部”,这个点代表合适的簇数量。

from sklearn.cluster import KMeans
import matplotlib.pyplot as plt

# 使用肘部法确定最佳 K 值
inertia = []
k_values = range(1, 11)
for k in k_values:
    kmeans = KMeans(n_clusters=k, random_state=42)
    kmeans.fit(scaled_customer_data)
    inertia.append(kmeans.inertia_)

# 绘制肘部法图形
plt.figure(figsize=(8, 5))
plt.plot(k_values, inertia, marker='o')
plt.title('Elbow Method For Optimal K')
plt.xlabel('Number of Clusters (K)')
plt.ylabel('Inertia')
plt.show()

从肘部法的结果图中可以看到,在 ( K = 3 ) 附近,曲线出现明显的弯曲,因此我们选择 ( K = 3 ) 作为聚类数。

K-Means 聚类分析

基于肘部法的结果,我们使用 K-Means 算法对客户进行聚类,将所有客户分为三类,并为每个客户分配一个聚类标签。

# K-Means 聚类分析(选择 K=3)
kmeans = KMeans(n_clusters=3, random_state=42)
customer_data['Cluster'] = kmeans.fit_predict(scaled_customer_data)
结果分析与可视化

为了更好地理解每个聚类的特征,我们对每个群组进行了平均特征的分析,并通过可视化手段展示聚类结果。

# 查看每个群组的平均特征
cluster_summary = customer_data.groupby('Cluster').mean()
print(cluster_summary)

# 可视化聚类结果
plt.figure(figsize=(8, 5))
plt.scatter(scaled_customer_data[:, 0], scaled_customer_data[:, 1], c=customer_data['Cluster'], cmap='viridis')
plt.title('Customer Segmentation with K-Means Clustering')
plt.xlabel('TotalQuantity (scaled)')
plt.ylabel('TotalPrice (scaled)')
plt.show()

通过分析,我们将客户分为以下三类:

  • 群组 1: 高消费客户,购买频繁,商品单价较高。
  • 群组 2: 中等消费客户,购买较为规律,整体消费较平衡。
  • 群组 3: 低消费客户,购买量少,可能是偶尔购物的客户。

这些信息可以帮助企业根据不同客户群体的行为特征制定差异化的营销策略,例如对高价值客户提供专属折扣和服务,对低消费客户进行定向推广以提升其购买频次。

结论

通过应用 K-Means 聚类算法,我们成功地对客户进行了分群,揭示了不同客户群体在购买行为上的显著差异。这些分群结果为企业制定更加精准的市场营销策略提供了数据支持,帮助提升客户满意度和忠诚度。

完整代码

以下为项目的完整代码,包括数据读取、清理、特征工程、标准化处理、聚类分析及结果展示。

import pandas as pd
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt

# 1. 读取数据集
file_path = 'Online Retail.xlsx'
data = pd.read_excel(file_path)

# 2. 数据清理
# 去除缺失的 CustomerID 行
data_cleaned = data.dropna(subset=['CustomerID'])

# 将 InvoiceNo 转为字符串类型
data_cleaned['InvoiceNo'] = data_cleaned['InvoiceNo'].astype(str)

# 删除退货订单及交易金额小于 0 的记录
data_cleaned = data_cleaned[~data_cleaned['InvoiceNo'].str.startswith('C')]
data_cleaned = data_cleaned[data_cleaned['Quantity'] > 0]
data_cleaned = data_cleaned[data_cleaned['UnitPrice'] > 0]

# 计算总消费金额
data_cleaned['TotalPrice'] = data_cleaned['Quantity'] * data_cleaned['UnitPrice']

# 3. 特征工程
customer_data = data_cleaned.groupby('CustomerID').agg(
    TotalQuantity=('Quantity', 'sum'),
    TotalPrice=('TotalPrice', 'sum'),
    MaxQuantity=('Quantity', 'max'),
    MaxPrice=('UnitPrice', 'max'),
    AvgQuantity=('Quantity', 'mean'),
    AvgPrice=('UnitPrice', 'mean')
).reset_index()

# 4. 数据标准化
scaler = StandardScaler()
scaled_customer_data = scaler.fit_transform(customer_data[['TotalQuantity', 'TotalPrice', 'MaxQuantity', 'MaxPrice', 'AvgQuantity', 'AvgPrice']])

# 5. 使用肘部法确定最佳 K 值
inertia = []
k_values = range(1, 11)
for k in k_values:
    kmeans = KMeans(n_clusters=k, random_state=42)
    kmeans.fit(scaled_customer_data)
    inertia.append(kmeans.inertia_)

# 绘制肘部法图形
plt.figure(figsize=(8, 5))
plt.plot(k_values, inertia, marker='o')
plt.title('Elbow Method For Optimal K')
plt.xlabel('Number of Clusters (K)')
plt.ylabel('Inertia')
plt.show()

# 6. K-Means 聚类分析(选择 K=3)
kmeans = KMeans(n_clusters=3, random_state=42)
customer_data['Cluster'] = kmeans.fit_predict(scaled_customer_data)

# 7. 查看每个群组的平均特征
cluster_summary = customer_data.groupby('Cluster').mean()
print(cluster_summary)

# 8. 可视化聚类结果
plt.figure(figsize=(8, 5))
plt.scatter(scaled_customer_data[:, 0], scaled_customer_data[:, 1], c=customer_data['Cluster'], cmap='viridis')
plt.title('Customer Segmentation with K-Means Clustering')
plt.xlabel('TotalQuantity (scaled)')
plt.ylabel('TotalPrice (scaled)')
plt.show()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

机智的小神仙儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值