一般来讲,在传统零售行业中80%的收益来自于20%的客户,所以对客户的价值进行分类显得尤为重要,而在本文咱们基于批发经销商客户的真实消费数据,创建K-means聚类模型来对客户价值进行细分。算法
1. 数据来源及背景app
2. 明确分析目的dom
3. 数据探索分析机器学习
4. 数据预处理布局
5. 构建模型学习
6. 客户价值细分spa
数据来源: http://archive.ics.uci.edu/ml/machine-learning-databases/00292;code
数据背景: 这是某批发经销商客户在各种型产品的年度支出数据集. 该数据集样本容量为440, 共有8个特征, 其分别为: 客户渠道, 客户所在地区, 以及在新鲜产品, 奶制品, 食品杂货, 冷冻产品, 洗涤剂和纸制品, 熟食产品这6种类型产品的年度支出.orm
经过提出一系列问题, 明确咱们的分析目的:blog
1) 各种产品的年度支出平均水平如何?哪一个产品最高?哪一个又最低?
2) 如何对这些客户进行分类呢?他们的消费行为又是怎样的呢?
3) 商家该如何根据分类结果制定营销计划呢?
1. 查看前2行和后2行
import pandas as pd df = pd.read_csv(r'D:\Data\Wholesale customers data.csv') pd.set_option('display.max_rows', 4) df
可经过以上看出咱们的数据维度的确是440行×8列, 以及每列都是数字, 究竟是字符串类型仍是数值类型, 须要进一步探索.
2. 查看数据总体信息
df.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 440 entries, 0 to 439 Data columns (total 8 columns): Channel 440 non-null int64 Region 440 non-null int64 Fresh 440 non-null int64 Milk 440 non-null int64 Grocery 440 non-null int64 Frozen 440 non-null int64 Detergents_Paper 440 non-null int64 Delicassen 440 non-null int64 dtypes: int64(8) memory usage: 27.6 KB
经过查看数据总体信息, 能够肯定每列都是数值型, 且均为64位整数型;另外, 也能够看出数据里是没有缺失值的, 即所有为440.
数据类型如今已经肯定了, 接下来寻找咱们第一个问题的答案了.
3. 描述性统计
df.describe()
1) 各种产品的年度支出平均水平如何?哪一个产品最高?哪一个又最低?
这里的平均水平用平均数和中位数这二者中的哪一个合适呢?经过分别对比各种型产品的平均数和中位数, 发现平均数都大于中位数, 呈现右偏分布, 显然这里采用中位数来表明较为稳当.
各种型产品的年度支出平均水平分别为: 新鲜产品8504.0m.u.、奶制品3627.0m.u.、食品杂货4755.5m.u.、冷冻产品1526.0m.u.、洗涤剂和纸质品816.5m.u.、熟食产品965.5m.u.
其中, 新鲜产品排名第一,第二是食品杂货,第3、第四和第五分别是奶制品、冰冻产品和熟食产品,第六则是洗涤剂和纸质品.
对于第二个问题,咱们利用k-means聚类模型来对其进行分类,而在建模以前,咱们须要对数据进行数据预处理
1. 数据清洗
1) 缺失值处理
没有缺失值, 所以不用缺失值处理
2) 异常值处理
在处理异常值以前, 先来经过箱线图查看异常值.
import seaborn as sns import matplotlib.pyplot as plt def get_boxplot(data, start, end): fig, ax = plt.subplots(1, end-start, figsize=(24, 4)) for i in range(start, end): sns.boxplot(y=data[data.columns[i]], data=data, ax=ax[i-start]) get_boxplot(df, 2, 8)
能够看到以上6个连续型变量均有不一样程度的异常值, 因为k-means算法对异常值较敏感, 所以选择剔除它
def drop_outlier(data, start, end): for i in range(start, end): field = data.columns[i] Q1 = np.quantile(data[field], 0.25) Q3 = np.quantile(data[field], 0.75) deta = (Q3 - Q1) * 1.5 data = data[(data[field] >= Q1 - deta) & (data[field] <= Q3 + deta)] return data del_df = drop_outlier(df, 2, 8) print("原有样本容量:{0}, 剔除后样本容量:{1}".format(df.shape[0], del_df.shape[0])) get_boxplot(del_df, 2, 8)
原有样本容量:440, 剔除后样本容量:318
在剔除一次异常值以后, 6个连续变量的波动幅度也都都大体接近, 你可能会问为何还有异常值存在? 如今的异常值是相对于新数据集产生的, 而咱们把原数据集中的异常值已经剔除了, 一般来讲, 对于异常值只需剔除一次便可, 若是完全剔除的话, 样本容量可能会有大幅度的变化, 好比:
df_new = df.copy() #直到第10次的时候图像上才没有出现异常值 for i in range(10): df_new = drop_outlier(df_new, 2, 8) print("原有样本容量:{0}, 完全剔除后样本容量:{1}".format(df.shape[0], df_new.shape[0])) get_boxplot(df_new, 2, 8)
原有样本容量:440, 完全剔除后样本容量:97
能够看到如今的数据集中已经不存在异常了, 可是样本容量也从440大幅度降低为97, 所以这里不建议完全删除.
2. 数据变换
对数据中的离散型变量和连续型变量分别进行适当的变换,以适应模型的要求
1) 离散型变量
将离散型变量处理成哑变量.
del_df['Channel'] = del_df.Channel.astype(str) del_df['Region'] = del_df.Region.astype(str) del_df = pd.get_dummies(del_df)
2) 连续型变量
因为连续型变量的数值范围有大有小, 为消除其对聚类结果的影响, 这里采用z-score进行归一化处理
for i in range(6): field = del_df.columns[i] del_df[field] = del_df[field].apply(lambda x: (x - del_df[field].mean()) / del_df[field].std())
数据预处理这部分的工做已大体完成,下一步进行模型构建.
选取一个初始的k值, 来进行构建k-means聚类模型
1. 构建K=2的聚类模型
from sklearn.cluster import KMeans km = KMeans(n_clusters=2, random_state=10) km.fit(del_df) print(km.cluster_centers_) print(km.labels_)
[[ 0.08057098 -0.36005276 -0.42021772 0.11899282 -0.66737726 -0.10885484 0.97333333 0.02666667 0.2 0.10222222 0.69777778] [-0.19492979 0.8710954 1.01665578 -0.28788585 1.61462241 0.26335849 0.13978495 0.86021505 0.10752688 0.07526882 0.8172043 ]] [1 1 0 1 1 1 0 1 1 0 1 1 1 0 1 1 0 0 0 1 0 0 0 0 0 0 0 1 1 1 0 1 1 1 0 0 1 0 0 1 0 1 1 1 1 0 0 1 0 0 1 0 0 0 0 1 1 0 1 0 0 1 0 1 0 0 0 1 1 1 0 0 1 1 0 1 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 0 0 1 1 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 1 1 1 0 0 1 0 1 0 0 0 0 0 1 0 0 0 1 1 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 1 1 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 1 0 1 0 1 1 1 1 0 1 1 0 0 1 1 0 0 0 0 0 0 0 0]
将客户分为两类合适吗?咱们经过迭代的方式来选择合适的k值.
2. 迭代选择合适的k值
import matplotlib.pyplot as plt K = range(1, 10) sse = [] for k in K: km = KMeans(n_clusters=k, random_state=10) km.fit(del_df) sse.append(km.inertia_) plt.figure(figsize=(8, 6)) plt.plot(K, sse, '-o', alpha=0.7) plt.xlabel("K") plt.ylabel("SSE") plt.show()
根据肘部法则, 选择K=2, 也就是说将客户分红两类.
from pandas.plotting import parallel_coordinates #训练模型 km = KMeans(n_clusters=2, random_state=10) km.fit(del_df) centers = km.cluster_centers_ labels = km.labels_ customer = pd.DataFrame({'0': centers[0], "1": centers[1]}).T customer.columns = del_df.keys() df_median = pd.DataFrame({'2': del_df.median()}).T customer = pd.concat([customer, df_median]) customer["category"] = ["customer_1", "customer_2", 'median'] #绘制图像 plt.figure(figsize=(12, 6)) parallel_coordinates(customer, "category", colormap='flag'') plt.xticks(rotation = 15) plt.show()
将各种型产品年度支出的聚类中心以及中位数绘制如上图所示, 那么咱们的第二个问题也就有了答案.
2) 如何对这些客户进行分类呢?他们的消费行为又是怎样的呢?
咱们经过k-means聚类模型将这些客户分为两群: 客户群1和客户群2.
就六种类型产品的年度支出来看, 客户群1在冷冻产品上最高, 在洗涤剂和纸制品上最低; 客户群2在冷冻产品上则最低, 在洗涤剂和纸制品上则最高. 另外, 客户群2在这六种产品的年度支出聚类中心均位于中位数水平之上上, 所以可将客户群2视为重要价值客户, 而客户群1则为通常价值客户.
最后, 咱们将全部客户的聚类结果绘制在平行坐标图上
#将聚类后的标签加入数据集 del_df['category'] = labels del_df['category'] = np.where(del_df.category == 0, 'customer_1', 'customer_2') customer = pd.DataFrame({'0': centers[0], "1": centers[1]}).T customer["category"] = ['customer_1_center', "customer_2_center"] customer.columns = del_df.keys() del_df = pd.concat([del_df, customer]) #对6类产品每一年消费水平进行绘制图像 df_new = del_df[['Fresh', 'Milk', 'Grocery', 'Frozen', 'Detergents_Paper', 'Delicassen', 'category']] plt.figure(figsize=(18, 6)) parallel_coordinates(df_new, "category", colormap='cool') plt.xticks(rotation = 15) plt.show()
经过上图能够看出模型的聚类效果较为理想, 同时也显示出客户群2(重要价值客户)相对于客户群1(通常价值客户)的数量较少, 毕竟重要的老是占少数.
针对这些结果, 该采起什么措施呢?来到咱们的第三个问题
3) 商家该如何根据分类结果制定营销计划呢?
就六大类型产品来讲, 可经过问卷的方式来调研改善店铺内布局以及增长产品种类是否会影响客户的购买行为; 另外, 根据聚类结果发现高价值客户的来源倾向于渠道2, 可加大在该渠道上的宣传力度; 最后,可进行一些打折促销活动,刺激客户的购买行为.
参考资料:
网易云课堂《吴恩达机器学习》
《数据分析与挖掘实战》
声明: 本文仅用于学习交流