1 项目背景
本次分析数据来源CDNow网站的用户在1997年1月1日至1998年6月30日期间内购买CD订单明细,对订单明细进行RFM模型的K-Means聚类分析并提出运营策略建议
2 数据探索
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns#读取数据
columns = ['用户ID','订单时间','订单数量','订单金额']
#命名表头
data = pd.read_table("CDNOW.txt",names = columns,sep = '\s+')
data.head()
#查看数据形状
data.shape
#数据类型和结构
data.info()
-- 每个数据一共4列,分别是用户ID、订单时间、订单数量、订单金额,数据类型都是数值型
3 数据预处理
3.1 重复值、缺失值、异常值
# 重复值查看
data.duplicated().value_counts()
#删除重复值
data=data.drop_duplicates()
-- 删除255个重复值
# 观察订单金额为0的值
data[data['订单金额']==0].describe()
-- 共有80个,订单数均为1,可能是未付款订单或免费活动,没有明显价值,可以剔除
data=data.drop(index=data[data['订单金额']==0].index)
3.2 数据类型调整
# 将订单时间转换为日期格式
data.订单时间=pd.to_datetime(data.订单时间,format = '%Y%m%d')
data.info()
3.3 数据准备
data.订单时间.describe(include='all')
-- 数据集的时间在1997-01-01到1998-06-30日,因此将此次观察日期定义为1998年6月30日
3.3.1 关键字段提取
RFM模型的定义:R为最近一次下单时间,F为购买频次,M为购买金额。提取所需要的字段信息:
#R
data['时间间隔']=pd.to_datetime('1998-06-30')-data.订单时间
data['时间间隔'] = data['时间间隔'].apply(lambda x:x.days) #去掉days
rfm = data.groupby(['用户ID']).agg({'时间间隔':'min','订单数量':'count','订单金额':'sum'})
rfm.head()
3.3.2 标准化处理
rfm = (rfm - rfm.mean(axis = 0))/(rfm.std(axis = 0)) # 处理后的数据均值为0,标准差为1
rfm.head()
#重置索引
rfm.reset_index(inplace=True)
#重命名列
rfm.columns = ['用户ID','R','F','M']
rfm.head()
-- 完成数据预处理
4 模型搭建和评估
利用K-means算法对客户进行聚类
结合业务,分析客户特征,分析客户价值
4.1 客户聚类
4.1.1 手肘法和轮廓系数找最优K
#手肘法,通过学习曲线看SSE的变化,找到一个明显的拐点,在该位置后SSE曲线趋于平缓
from sklearn.cluster import KMeans
sse = []
for i in range(2,10): # 不同簇的个数
km = KMeans(n_clusters=i).fit(rfm.loc[:,['R','F','M']])
sse.append(km.inertia_)
plt.plot(range(2,10),sse,marker='o')
-- 在K=4、5的时候SSE曲线趋于平缓,再用轮廓系数看一下
from sklearn.metrics import silhouette_score
#轮廓系数:簇内差异小,簇外差异大
#越接近1表示样本与自己所在的簇中的样本很相似,并且与其他簇中的样本不相似
score=[]
for i in range(2,10):
km = KMeans(n_clusters=i).fit(rfm.loc[:,['R','F','M']])
score.append(silhouette_score(rfm.loc[:,['R','F','M']],km.labels_))
plt.plot(range(2,10),score,marker='o')
-- 选择最高点K=4进行聚类
4.1.2 数据聚类
n_clusters=4
#进行K=4的聚类
kmodel=KMeans(n_clusters=n_clusters).fit(rfm.loc[:,['R','F','M']])
kmodel
#查看质心
centroid=kmodel.cluster_centers_
centroid
#查看每个样本对应的类别
y_pred=kmodel.labels_
y_pred
#把类别添加到rfm表中
rfm['类别']=y_pred
rfm.head()
#查看各类别人数
rfm['类别'].value_counts()
4.2 客户分类可视化
#把类别人数和质心转换成表格形式,拼接在一起
r1 = pd.Series(y_pred).value_counts() #类别人数
r2 = pd.DataFrame(centroid) # 聚类中心
r = pd.concat([r2,r1],axis=1)
r.columns = list(rfm.loc[:,['R','F','M']]) + ['聚类个数']
r
# 中文和负号的正常显示
plt.rcParams['font.sans-serif'] = 'SimHei'
plt.rcParams['font.size'] = 12.0
plt.rcParams['axes.unicode_minus'] = False
# 所有簇中心坐标值中最大值和最小值
max = r2.values.max()
min = r2.values.min()
# 绘图
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, polar=True)
center_num = r.values
feature = ['最近一次消费时间-R',"消费频次-F", "消费金额-M"]
N = len(feature)
for i, v in enumerate(center_num):
# 设置雷达图的角度,用于平分切开一个圆面
angles = np.linspace(0, 2 * np.pi, N, endpoint=False)
# 为了使雷达图一圈封闭起来,需要下面的步骤
center = np.concatenate((v[:-1], [v[0]]))
angles = np.concatenate((angles, [angles[0]]))
# 绘制折线图
ax.plot(angles, center, 'o-', linewidth=2, label="第%d类人群,%d人" % (i + 1, v[-1]))
# 填充颜色
ax.fill(angles, center, alpha=0.25)
# 添加每个特征的标签
ax.set_thetagrids(angles * 180 / np.pi, feature, fontsize=15)
# 设置雷达图的范围
ax.set_ylim(min - 0.1, max + 0.1)
# 添加标题
plt.title('客户群特征分析图', fontsize=20)
# 添加网格线
ax.grid(True)
# 设置图例
plt.legend(loc='upper right', bbox_to_anchor=(1.3, 1.0), ncol=1, fancybox=True, shadow=True)# 显示图形
plt.show()
5 客户价值分析
R:最近消费时间 F:消费频次 M:消费金额
经分析,把客户群体分为以下4类:
第1类人群:占比28.73%,RMF三个值都比较低,属于低价值用户
第2类人群:占比3.6%,F和M较高,R低,属于重要保持用户
第3类人群:占比67.52%(最多),R值较高,属于一般发展用户
第4类人群:只有22人,F和M特别高,R低,属于高价值的重要保持用户
用户特点及策略:
(1)重要保持用户:
消费次数(F)和消费金额(M)高,最近消费时间(R)低
是公司的高价值用户,对公司贡献最大,所占比例小,主要目标是促进提高满意度,延长用户生命周期。可采取个性化营销,如设计VIP服务、提供高质量产品、与客户互动了解情况等,促进用户回流。
(2)重要发展用户: 消费次数(F)和消费金额(M)低,最近消费时间(R)高
此类客户当前价值不高,但是所在比例最大,有发展潜力,主要目标是提升其购买频次和金额,可采取交叉销售、个性化推荐、组合优惠券等策略,提升单次购买的订单金额及促进重复购买。
(3)低价值用户:
消费次数(F)、消费金额(M)和最近消费时间(R)三个值都低
此类用户优先级最低,可能在打折促销、打造爆款时会进行购买。
小结:各类别用户都明显出现R值低的情况,说明用户留存较低,结合业务场景(CDNow在线CD零售平台),属于用户消费频次高的场景,应引起重视,找到产品问题,提高用户留存,培养用户忠诚度