假如你拥有一个超市购物中心,并通过会员卡拥有客户的一些基本数据,例如客户ID,年龄,性别,年收入和消费得分。消费得分是您根据定义的参数(例如客户行为和购买数据)分配给客户的属性。
该数据包含有关客户的基本信息(ID,年龄,性别,收入,支出得分)。
具体数据列如下:
顾客ID:分配给客户的唯一ID
性别:客户性别
年龄:客户年龄
年度收入(k $):客户的年收入
消费得分:(1-100)商场根据顾客行为和消费性质分配的分数
本案例将使用Linkage和dendrogram函数绘制聚类树,同时使用AgglomerativeClustering函数生成聚类标签,最后,将使用绘图的方法,将聚类效果进行展示。
from scipy.spatial.distance import pdist,squareform
from scipy.cluster.hierarchy import linkage
from scipy.cluster.hierarchy import dendrogram
import pandas as pd
org_data = pd.read_csv("Mall_Customers.csv")
org_data.head()
去掉CustomerID,同时对Genre进行哑变量处理。代码如下:
org_data.drop("CustomerID",axis=1,inplace=True)
org_data = pd.get_dummies(org_data)
org_data.head()
先将数据标准化处理,代码如下:
import matplotlib.pyplot as plt
import numpy as np
org_data = org_data.apply(lambda x: (x - np.mean(x))/np.std(x))
org_data.head()
绘制聚类树图,并添加辅助线,代码如下:
row_clusters = linkage(pdist(org_data,metric='euclidean'),method='ward')
row_dendr = dendrogram(row_clusters)
plt.tight_layout()
plt.ylabel('Euclidean distance')
plt.plot([0,2000],[12,12],c='red',linestyle='--')
plt.show()
通过观察聚类树图,我们可以将数据分成4簇。
from sklearn.cluster import AgglomerativeClustering
ac=AgglomerativeClustering(n_clusters=4,affinity='euclidean',linkage='ward')
labels = ac.fit_predict(org_data)
print ('cluster labels:%s'%labels)
这里使用TSNE先将数据降到2维,然后绘制散点图,代码如下:
from sklearn.manifold import TSNE
tsne = TSNE(n_components=2,learning_rate=10)
pdata = tsne.fit_transform(org_data)
colors = ["red","blue","green","orange"]
for t in range(4):
loc = np.where(labels == t)
plt.scatter(pdata[loc,0],pdata[loc,1],c = colors[t],label =str(t))
plt.legend(loc=2)
plt.show()
org_data = pd.read_csv("Mall_Customers.csv")
org_data.drop("CustomerID",axis=1,inplace=True)
org_data = pd.get_dummies(org_data)
org_data.groupby(labels).median()
pd.Series(labels).value_counts()
# 1 59
# 3 53
# 0 47
# 2 41
# dtype: int64
四类用户的特点
[0]第一类:大龄男性
[1]第二类:年轻女性,消费主力
[2]第三类:年轻男性,消费主力
[3]第四类:大龄女性
如果只关注年收入和消费得分,则可基于这两个指标来聚类,代码如下:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
org_data = pd.read_csv("Mall_Customers.csv")
org_data_std = org_data.iloc[:,[3,4]].apply(lambda x:(x - np.min(x))/np.std(x))
row_clusters = linkage(pdist(org_data_std,metric='euclidean'),method='ward')
row_dendr = dendrogram(row_clusters)
plt.tight_layout()
plt.ylabel('Euclidean distance')
plt.plot([0,2000],[5,5],c='red',linestyle='--')
plt.show()
如图所示,可以将数据分成5类。
from sklearn.cluster import AgglomerativeClustering
ac=AgglomerativeClustering(n_clusters=4,affinity='euclidean',linkage='ward')
labels = ac.fit_predict(org_data_std)
print ('cluster labels:%s'%labels)
#
cluster labels:[4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4
3 4 3 4 3 4 2 4 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 0 1 0 1 2 1 0 1 0 1 0 1 0 1 2 1 0 1 2 1
0 1 0 1 0 1 0 1 0 1 0 1 2 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
1 0 1 0 1 0 1 0 1 0 1 0 1 0 1]
colors = ["red","blue","green","orange","purple"]
data_std = np.array(org_data_std)
for t in range(5):
loc = np.where(labels == t)
plt.scatter(data_std[loc,0],data_std[loc,1],c = colors[t],label =str(t))
plt.show()
将原始数据,按新标签的维度,统计中位数,可得:
org_data['type'] = labels
pd.Series(labels).value_counts()
#
2 85
1 39
0 32
4 23
3 21
dtype: int64
org_data.iloc[:,[3,4,5]].groupby('type').median()
如上表结果,可知:
【0】类,平均年收入较高,但是消费得分低,属于不太愿意消费的人群
【1】类,平均年收入和消费得分均较高,属于抢手型的客户
【2】类,平均年收入和消费得分均一般的客户,属于大众用户型
【3】类,平均年收入较低,但是消费得分较高,属于乐观消费型客户
【4】类,平均年收入和消费得分均低,属于低端用户群
如上两种做法不一样。对此,你有什么想法呢?欢迎交流讨论。
往期回顾
基于Python实现相关分析案例
使用Scrapy,帮你快速抓取网页数据(代码可下载)!
JupyterLab最全详解,如果你还在使用Notebook,那你就out了!
史上最全的Python基础语法知识清单