怎么利用Kmeans算法实现用户分类

描述

 

模式

 

一.项目背景

为了建立客户信息资源管理及运营模式,某公司希望通过客户的基本消费信息进行分析,
衡量客户价值和客户创利能力,优化客户资源,提高营销效率,避免不必要的资源

 

二.实现步骤

1.导包读入数据,筛选所需数据

# 导入所需库
import numpy as np
import pandas as pd
import datetime
import matplotlib.pyplot as plt
import time
import matplotlib.gridspec as gridspec
#import pyecharts

# 解决 matplotlib 显示中文、负号问题
plt.rcParams['font.family'] = 'SimHei'
plt.rcParams['axes.unicode_minus'] = False 

#获取数据
def get_data(file_path):
    #读取数据
    df1= pd.read_excel(file_path)
    # 提取 RFM 模型所需特征列:'订单编号','买家会员名','买家实际支付货款','订单付款时间','宝贝总数量'
    df2 = df1[['订单编号','买家会员名','买家实际支付金额','订单付款时间','宝贝总数量']]
    #返回数据
    return df2
2.数据重复值缺失值处理

#处理数据
def process_data(df):
    #判断有没有重复值
    if df.duplicated().sum()==0:
        print('无重复数据')
    else:
        #删除重复值
        df=df.drop_duplicates(inplace=True)
    #判断有没有缺失值
    if df.isnull().any().sum()==0:
        print('无缺失值')
    else:
        #删除缺失值
        df=df.dropna(inplace=True)
    #返回数据
    return df
3.获取RFMP各项值

#获取R值
def get_R(df):
    # 计算时间差
    time_minus =  datetime.datetime.now()- df['订单付款时间'] 
    # 将时间差转换成数字格式
    df['prior_R'] = time_minus.astype(str).str.findall('d+.*d*').map(lambda x: int(x[0]) + (int(x[1]) / 24) + 
                                                   (int(x[2]) / (24 * 60)) + (float(x[3]) / (24 * 3600)))
    # 按会员进行分组,确定每个会员最近一次购买离现在的时间间隔
    R = df.groupby('买家会员名')['prior_R'].min()
    return R


#获取FMP值,P值表示买家购买数量
def get_F_M_P(df):
    # 按会员进行分组,确定每个会员的订单数量
    F = df.groupby('买家会员名')['订单编号'].count()
    # 按会员进行分组,确定每个会员的实际支付金额
    M = df.groupby('买家会员名')['买家实际支付金额'].sum() 
    # 按会员进行分组,确定每个会员的宝贝总数量
    P = df.groupby('买家会员名')['宝贝总数量'].sum() 
    return (F,M,P)


#将RFMP数据合成DataFrame
def get_data(R,F,M,P):
    #列名称
    col_list = list('RFMP') 
    #创建DataFrame
    model_data = pd.DataFrame([], index=R.index) 
    #添加数据
    for col_names, values in zip(col_list, [R, F, M, P]):
          model_data[col_names] = values
    #类型转换
    model_data = model_data.astype(float)
    #返回数据
    return model_data
4.利用Kmeans算法进行分类

from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
from sklearn.preprocessing import StandardScaler, MinMaxScaler

#获取数据
df0 = model_data.iloc[:, 0:4]
#标准化数据
res_std = StandardScaler().fit_transform(df0)

#分类簇数
n_clusters = range(2, 7)
#评分标准
scores = []
#遍历每种分类
for i in range(len(n_clusters)):
    #训练模型
    clf = KMeans(n_clusters = n_clusters[i], random_state = 20).fit(res_std)
    #获取评分
    scores.append(silhouette_score(res_std, clf.labels_))
#获取最大评分索引
maxindex = scores.index(max(scores))
#初始画布
plt.figure(figsize = (8, 6), dpi = 100) 
#绘制图形
plt.plot(n_clusters, scores, linestyle = '-.', c = 'b', alpha = 0.6, marker = 'o')
#编辑最佳簇数
plt.axvline(x = n_clusters[maxindex], linestyle = '--', c = 'r', alpha = 0.5)
#设置标题
plt.title('RFMP的聚类轮廓系数图')
#设置y轴标签
plt.ylabel('silhouette_score')
#设置x轴标签
plt.xlabel('n_clusters')
#存储图形
plt.savefig('./RFMP聚类轮廓系数图.png')

 

模式
#获取最佳分簇数模型
clf = KMeans(n_clusters = 2, random_state = 20).fit(res_std)
#添加label
df0['labels'] = clf.labels_
df0

 

模式
  •  
  •  
  •  
# 统计一下两类用户之间的差异,发现两类客户之间数量相差过大
print(f"类别0所占比例为:{df0['labels'].value_counts().values[0] / df0.shape[0]} t 类别1所占的比例为:{df0['labels'].value_counts().values[1] / df0.shape[0]}")
df0['labels'].value_counts()

 

模式
#用均值来评估两类样本之间的LRFMP
R_avg = df0.groupby('labels').agg({'R': np.mean}).reset_index()
F_avg = df0.groupby('labels').agg({'F': np.mean}).reset_index()
M_avg = df0.groupby('labels').agg({'M': np.mean}).reset_index()
P_avg = df0.groupby('labels').agg({'P': np.mean}).reset_index()

# 绘制相关的条形图
def plot_bar(df_list, nrow, ncol):
    #初始画布
    fig, axs = plt.subplots(nrow, ncol, figsize = (2 * (ncol + 2), 2.5), dpi = 100)
    #遍历每个坐标系
    for i in range(len(axs)):
        #获取坐标系
        ax = axs[i]
        #获取数据
        df = df_list[i]
        #画柱状图
        ax.bar(df.iloc[:, 0], df.iloc[:, 1], color = 'm', alpha = 0.4, width = 0.5)
        #获取RFMP标签对应数值
        for x, y in enumerate(df.iloc[:, 1].tolist()):
            #标注数据
            ax.text(x, y / 2, '%.0f' % y, va = 'bottom', ha = 'center', fontsize = 12)
        #设置x轴刻度
        ax.set_xticks([0, 1])
        #设置y轴刻度
        ax.set_yticks(())
        #设置小标题
        ax.set_title(f'{df.columns[1]}')
    #设置大标题
    plt.suptitle('两类客户的RFMP均值差异', y = 1.1, fontsize = 14)
    #存储图片
    plt.savefig('./两类客户LRFMP均值差异.png')
#获取数据
df_list = [ R_avg, F_avg, M_avg, P_avg]
#绘制图形
plot_bar(df_list, 1, 4)

总结:分为两类用户效果确实很明显,但是分析还是有点一刀切,我们发现图中四类效果也
不是很差,后期感兴趣读者可以进行四类用户分类,在这里主要还是给大家一个思维拓展.

 

模式
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分