K-Means(K均值)是聚类最常用的方法之一,基于点与点距离的相似度来计算最佳类别归属。
数据来源业务部门,这些数据是关于客户的,苦于没有分析入手点希望数据部门通过对这些数据的分析,给业务部门一些启示,或者提供数据后续分析或者业务思考的建议。
基于以上的场景的描述和需求,由于业务部门可以自己做一些描述性的统计分析,以及此次数据属于探索性数据分析,没有之前的参考案例。故考虑对客户进行聚类分析,分析客户的一些特点。
数据源链接:https://pan.baidu.com/s/1gx0q2k9HtTBM-T7xW3oD2Q
提取码:1k95
数据描述:
- USER_ID:客户id
- AVG_ORDERS:平均用户订单数量
- AVG_MONEY:平均订单价值
- IS_ACTIVE:是否活跃
- SEX:性别(0,1,2分别代表未知,男,女)
1.导入库
# 导入库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans #Kmeans
from sklearn.preprocessing import MinMaxScaler#数据标准化包
# x效果评估模块
from sklearn.metrics import silhouette_score , calinski_harabaz_score
#忽略警告信息
import warnings
warnings.filterwarnings('ignore')
#解决中文乱码问题
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
2.导入数据文件
# 导入数据文件
raw_data = pd.read_csv('F:pythonpython数据分析与数据运营课本数据chapter4cluster.txt')
# 数值型特征
numeric_features = raw_data.iloc[:,1:3]
raw_data.head()
numeric_features.head()
3.数据标准化
# 数据标准化
scaler = MinMaxScaler()
scaled_numeric_features = scaler.fit_transform(numeric_features)
print(scaled_numeric_features[:,:2])
4.训练模型
#设置聚类数量
n_clusters = 3
# random_state = 0的目的是保证每次训练时的初始值一致
model_kmeans = KMeans(n_clusters = n_clusters,random_state = 0)
model_kmeans.fit(scaled_numeric_features)
''’对象持久化:将模型保存至硬盘,便于后期使用时直接调用'''
import pickle
# dump:将python对象序列化保存至本地文件
pickle.dump(model_kmeans,open('my_model_object.pk1','wb'))
#load:从本地文件读取python对象并恢复实例对象
model_kmeans = pickle.load(open('my_model_object.pk1','rb'))
5.模型效果指标评估
# 输出总样本量,总特征数
n_sample,n_feature = raw_data.iloc[:,1:].shape
print('n_sample: %d n n_feature: %d'%(n_sample,n_feature))
n_sample: 1000
n_feature: 4
# 非监督式评估方法
# 平均轮廓系数
silhouette_s = silhouette_score (scaled_numeric_features,model_kmeans.labels_,metric ='euclidean')
# calinski和harabaz得分
calinski_harabaz_s = calinski_harabaz_score(scaled_numeric_features,model_kmeans.labels_)
print('silhouette_s: %f n calinski_harabaz_s: %f'%(silhouette_s,calinski_harabaz_s))
silhouette_s: 0.634086
calinski_harabaz_s: 2860.821834
silhouette_s大于0.5,说明聚类质量较优。优秀与否的基本原则是不同类别间是否具有显著的区分效果。
6.合并数据和特征
# 整合上面的聚类标签到原始数据中
kmeans_labels = pd.DataFrame(model_kmeans.labels_ , columns= ['labels'])
#组合原始数据与标签
kmeans_data = pd.concat((raw_data,kmeans_labels),axis = 1)
kmeans_data.head()
7.计算不同类别的样本量和占比
#计数
label_count = kmeans_data.groupby('labels')['SEX'].count()
#占比
label_count_rate = label_count/kmeans_data.shape[0]
kmeans_record_count = pd.concat((label_count,label_count_rate),axis=1)
kmeans_record_count.columns = ['record_count','record_rate']
kmeans_record_count
# 计算样本容量
customer_count = kmeans_record_count.record_count.sum()
customer_count
1000
# 画图
plt.pie(kmeans_record_count.record_rate,
autopct="%3.1f%%",
labels=kmeans_record_count.index )
plt.title('不同类别的样本量和占比')
样本数量共1000人
1)分类为‘0’332人,占33.2%,
2)分类为‘1’337人,占33.7%,
3)分类为‘2’331人,占33.1人
8.计算不同聚类类别数值型特征
# 查看一下数值型特征的均值情况
kmeans_numeric_features = kmeans_data.groupby('labels')[['AVG_ORDERS','AVG_MONEY']].mean()
kmeans_numeric_features
kmeans_numeric_features.plot()
3个分类中,AVG_ORDERS和AVG_MONEY有轻微变化。
9.计算不同聚类类别分类类型特征
9.1 不同活跃度在不同标签中的占比
kmeans_data['n']=1
kmeans_active_count = kmeans_data.groupby(['labels','IS_ACTIVE'])['n'].count().unstack()
kmeans_active_count
# 'labels = 0' 时,活跃与不活跃用户占比
plt.pie(kmeans_active_count.iloc[0,:],
autopct="%3.1f%%",
labels=kmeans_active_count.columns
)
plt.title('labels = 0')
# 'labels = 1' 时,活跃与不活跃用户占比
plt.pie(kmeans_active_count.iloc[1,:],
autopct="%3.1f%%",
labels=kmeans_active_count.columns
)
plt.title('labels = 1')
# 'labels = 2' 时,活跃与不活跃用户占比
plt.pie(kmeans_active_count.iloc[2,:],
autopct="%3.1f%%",
labels=kmeans_active_count.columns
)
plt.title('labels = 2')
由上面的3个饼图可知,用户是否活跃对标签的影响不大,在各分类中,活跃与不活跃用户基本各占50%。
9.2不同性别在不同标签中的占比
kmeans_sex_count = kmeans_data.groupby(['labels','SEX'])['n'].count().unstack()
kmeans_sex_count
# 'labels = 0' 时,各性别用户占比
plt.pie(kmeans_sex_count.iloc[0,:],
autopct="%3.1f%%",
labels=kmeans_sex_count.columns
)
plt.title('labels = 0')
# 'labels = 1' 时,各性别用户占比
plt.pie(kmeans_sex_count.iloc[1,:],
autopct="%3.1f%%",
labels=kmeans_sex_count.columns
)
plt.title('labels = 1')
# 'labels = 2' 时,各性别用户占比
plt.pie(kmeans_sex_count.iloc[2,:],
autopct="%3.1f%%",
labels=kmeans_sex_count.columns
)
plt.title('labels = 2')
由上面的3个饼图可知,性别对分类的影响比较大,近似可以看做每个性别类型对应一个分类。
总结:
通过kmeans聚类分析主要得出以下结论:
- 使用 kmeans对客户信息进行聚类,共3个分类,silhouette_s大于0.5,说明聚类质量较优;
- 样本数量共1000人
- 分类为‘0’332人,占33.2%,
- 分类为‘1’337人,占33.7%,
- 分类为‘2’331人,占33.1人
- 3个分类中,AVG_ORDERS和AVG_MONEY有轻微变化;
- 用户是否活跃对标签的影响不大,在各分类中,活跃与不活跃用户基本各占50%;
- 用户性别对分类的影响比较大,近似可以看做每个性别类型对应一个分类。