查看原文
其他

Python数据挖掘实战:客户价值识别实现差异化管理

yang Python数据科学修炼之路 2021-08-08

       企业除了产品优势,更多的焦点是客户经营。企业没有“人”就变成“止”业,而人不光指企业的人力人才资源,还有企业的“衣食父母”——客户。客户千千万,如何识别出有价值的客户,将客户进行精细科学的划分,从而进行精准营销,对不同价值的客户类别提供个性化服务,制定相应的营销策略,实现利润最大化,是一个企业做大做强必须考虑并着手贯彻的重要举措之一。

        今天给大家介绍,怎么通过公司的数据,建立合理的客户价值评估模型,实现客户分类,识别不同客户的价值,从而为客户经营提供策略依据。


目  录

  • 1、背景和目标

  • 2、技术和分析方法

  • 3、读取数据,数据探索分析

  • 4、数据预处理,数据转换

  • 5、模型构建

  • 6、基于模型结果的分析应用




背景和目标




1、背景


1、航空公司业务竞争激烈,企业营销焦点从产品中心转为客户中心;

2、针对不同类型客户,进行精准营销,实现利润最大化;

3、建立合理的客户价值评估模型,进行客户分类,是解决问题的关键。

2、目标


1、借助航空公司客户数据,对客户进行分类;

2、对不同的客户类别进行特征分析,比较不同类客户的客户价值;

3、对不同价值的客户类别提供个性化服务,制定相应的营销策略。




技术和分析方法




1、涉及技术


A、RFM模型

作用是识别出高价值的客户

客户细分模型是通过三个指标:

    最近消费时间间隔(Recency)

    消费频率(Frequency)

    消费金额(Monetary)

传统RFM模型分析的属性分箱方法,如下图:

B、K-means聚类算法简介

聚类算法属于无监督机器学习算法,通过计算样本项之间的相似度(也称为样本间的距离),按照数据内部存在的数据特征将数据集划分为多个不同的类别,使类别内的数据比较相似,类别之间的数据相似度比较小。

闵可夫斯基距离(Minkowski):

  • 当p为1的时候是曼哈顿距离(Manhattan)

  • 当p为2的时候是欧式距离(Euclidean)

  • 当p为无穷大的时候是切比雪夫距离(Chebyshev)

算法思想(步骤):

a、选择初始化的k个类别中心a1,a2,...ak;

b、计算每个样本Xi到类别中心aj的距离,设定最近的类别j

c、将每个类别的中心点aj,替换为隶属该类别的所有样本的均值,作为新的质心。

d、重复上面两步操作,直到达到某个中止条件

中止条件为:组内最小平方误差MSE最小,或者达到迭代次数,或者簇中心点不再变化。

图解:




读取数据,数据探索分析




1、读取数据

一如既往的,先引入需要的包。

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib as mpl
import sklearn.datasets as ds
import matplotlib.colors
from sklearn.cluster import KMeans
%matplotlib inline

## 设置属性防止中文乱码
mpl.rcParams['font.sans-serif'] = [u'SimHei']
mpl.rcParams['axes.unicode_minus'] = False

利用pandas包,将数据读入Python环境,查看前10条,看长什么样子

data = pd.read_csv('C:\\Users\\Administrator\\Desktop\\air_data.csv', encoding='utf-8'
data.head(10)

从上面可以看到成功读入数据,数据的样子,读入10行,总共有44列,通过data.shape,可以看到数据有62988行,44列。还需要了解数据。

每个特征(列)的中英文对照如下:

MEMBER_NO会员卡号

FFP_DATE入会时间

FIRST_FLIGHT_DATE第一次飞行日期

GENDER性别

FFP_TIER会员卡级别

WORK_CITY工作地城市

WORK_PROVINCE工作地所在省份

WORK_COUNTRY工作地所在国家

AGE年龄

LOAD_TIME观测窗口的结束时间

FLIGHT_COUNT飞行次数

BP_SUM观测窗口总基本积分

EP_SUM_YR_1第一年精英资格积分

EP_SUM_YR_2第二年精英资格积分

SUM_YR_1第一年总票价

SUM_YR_2第二年总票价

SEG_KM_SUM观测窗口总飞行公里数

WEIGHTED_SEG_KM观测窗口总加权飞行公里数(Σ舱位折扣×航段距离)

LAST_FLIGHT_DATE末次飞行日期

AVG_FLIGHT_COUNT观测窗口季度平均飞行次数

AVG_BP_SUM观测窗口季度平均基本积分累积

BEGIN_TO_FIRST观察窗口内第一次乘机时间至MAX(观察窗口始端,入会时间)时长

LAST_TO_END最后一次乘机时间至观察窗口末端时长

AVG_INTERVAL平均乘机时间间隔

MAX_INTERVAL观察窗口内最大乘机间隔

ADD_POINTS_SUM_YR_1观测窗口中第1年其他积分(合作伙伴、促销、外航转入等)

ADD_POINTS_SUM_YR_2观测窗口中第2年其他积分(合作伙伴、促销、外航转入等)

EXCHANGE_COUNT积分兑换次数

avg_discount平均折扣率

P1Y_Flight_Count第1年乘机次数

L1Y_Flight_Count第2年乘机次数

P1Y_BP_SUM第1年里程积分

L1Y_BP_SUM第2年里程积分

EP_SUM观测窗口总精英积分

ADD_Point_SUM观测窗口中其他积分(合作伙伴、促销、外航转入等)

Eli_Add_Point_Sum非乘机积分总和

L1Y_ELi_Add_Points第2年非乘机积分总和

Points_Sum总累计积分

L1Y_Points_Sum第2年观测窗口总累计积分

Ration_L1Y_Flight_Count第2年的乘机次数比率

Ration_P1Y_Flight_Count第1年的乘机次数比率

Ration_P1Y_BPS第1年里程积分占最近两年积分比例

Ration_L1Y_BPS第2年里程积分占最近两年积分比例

Point_NotFlight非乘机的积分变动次数


2、数据探索分析

查看每个特征的数据类型和数量:

data.info()

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 62988 entries, 0 to 62987
Data columns (total 44 columns):
MEMBER_NO                  62988 non-null int64
FFP_DATE                   62988 non-null object
FIRST_FLIGHT_DATE          62988 non-null object
GENDER                     62985 non-null object
FFP_TIER                   62988 non-null int64
WORK_CITY                  60719 non-null object
WORK_PROVINCE              59740 non-null object
WORK_COUNTRY               62962 non-null object
AGE                        62568 non-null float64
LOAD_TIME                  62988 non-null object
FLIGHT_COUNT               62988 non-null int64
BP_SUM                     62988 non-null int64
EP_SUM_YR_1                62988 non-null int64
EP_SUM_YR_2                62988 non-null int64
SUM_YR_1                   62437 non-null float64
SUM_YR_2                   62850 non-null float64
SEG_KM_SUM                 62988 non-null int64
WEIGHTED_SEG_KM            62988 non-null float64
LAST_FLIGHT_DATE           62988 non-null object
AVG_FLIGHT_COUNT           62988 non-null float64
AVG_BP_SUM                 62988 non-null float64
BEGIN_TO_FIRST             62988 non-null int64
LAST_TO_END                62988 non-null int64
AVG_INTERVAL               62988 non-null float64
MAX_INTERVAL               62988 non-null int64
ADD_POINTS_SUM_YR_1        62988 non-null int64
ADD_POINTS_SUM_YR_2        62988 non-null int64
EXCHANGE_COUNT             62988 non-null int64
avg_discount               62988 non-null float64
P1Y_Flight_Count           62988 non-null int64
L1Y_Flight_Count           62988 non-null int64
P1Y_BP_SUM                 62988 non-null int64
L1Y_BP_SUM                 62988 non-null int64
EP_SUM                     62988 non-null int64
ADD_Point_SUM              62988 non-null int64
Eli_Add_Point_Sum          62988 non-null int64
L1Y_ELi_Add_Points         62988 non-null int64
Points_Sum                 62988 non-null int64
L1Y_Points_Sum             62988 non-null int64
Ration_L1Y_Flight_Count    62988 non-null float64
Ration_P1Y_Flight_Count    62988 non-null float64
Ration_P1Y_BPS             62988 non-null float64
Ration_L1Y_BPS             62988 non-null float64
Point_NotFlight            62988 non-null int64
dtypes: float64(12), int64(24), object(8)
memory usage: 21.1+ MB


查看每个特征的总条数以及五值分布:平均值、最大值、最小值、标准差、四分位数。

data.describe().T

查看缺失值情况:

data.isnull().sum().sort_values(ascending=False)

WORK_PROVINCE              3248
WORK_CITY                  2269
SUM_YR_1                    551
AGE                         420
SUM_YR_2                    138
WORK_COUNTRY                 26
GENDER                        3
Point_NotFlight               0
EP_SUM_YR_2                   0
AVG_FLIGHT_COUNT              0
LAST_FLIGHT_DATE              0
WEIGHTED_SEG_KM               0





数据预处理、数据转换




1、数据预处理

其实根据RFM模型的要求,我们不去过多关注其他特征,只需要选取和最近消费时间间隔(Recency)、 消费频率(Frequency)、消费金额(Monetary)相关的特征即可。

数据清洗,丢弃票价为空的记录:

# 保留总票价非空值
data=data[data['SUM_YR_1'].notnull() & data['SUM_YR_2'].notnull()]  
# 保留票价非零值或平均折扣率为零的值
term_1 = data['SUM_YR_1'] != 0
term_2 = data['SUM_YR_2'] != 0
term_3 = data['avg_discount'] == 0
data = data[term_1 | term_2 | term_3] 
# 导出数清洗后的数据
result = '../客户价值识别/data_cleaned.csv'  
data.to_csv(result, sep=",", encoding='utf-8')

2、特征提取、数据转换

原始数据中属性太多,根据航空公司客户价值LRFMC模型,选择与模型相关的六个属性,删除不相关、弱相关或冗余属性。根据RFM的需要,我们来选择需要的特征,
R是最近消费时间间隔(Recency),可以用LAST_TO_END(最后一次乘机时间至观察窗口末端时长);F是消费频率(Frequency),FLIGHT_COUNT(观测窗口内的飞行次数)

M是消费金额(Monetary),消费金额航空票价收到距离和舱位等级多种因素的影响,

舱位因素=舱位所对应的折扣系数AVG_DISCOUNT的平均值,距离因素=一定时间内累积的飞行里程SEG_KM_SUM航空公司的会员系统,用户的入会时间长短能在一定程度上影响客户价值,所以增加指标入会时间长度,即客户关系长度:会员入会时间距观测窗口结束的月数=观测窗口的结束时间-入会时间(单位:月),即LOAD_TIME-FFP_DATE。


这样,我们需要5个指标LRFMC:

L=LOAD_TIME-FFP_DATE(会员入会时间距观测窗口结束的月数=观测窗口的结束时间-入会时间(单位:月))

R=LAST_TO_END(客户最近一次乘坐公司距观测窗口结束的月数=最后一次。

F=FLIGHT_COUNT(观测窗口内的飞行次数)

M=SEG_KM_SUM(观测窗口的总飞行里程)

C=AVG_DISCOUNT(平均折扣率)

# 数据筛选
# 选出模型需要的特征
df=data[["FFP_DATE","LOAD_TIME","LAST_TO_END","FLIGHT_COUNT","SEG_KM_SUM","avg_discount"]]
df.head()

# 构造LRFMC
def STRCTURE_LRFMC(data_set):
#     data_set=data_set[["FFP_DATE","LOAD_TIME","LAST_TO_END","FLIGHT_COUNT","SEG_KM_SUM","avg_discount"]]
    dt_FFP_DATE=pd.to_datetime(data_set["FFP_DATE"])
    dt_LOAD_TIME=pd.to_datetime(data_set["LOAD_TIME"])
    FFP_LOAD_DATE=dt_LOAD_TIME-dt_FFP_DATE
    df2=data_set.copy()
    df2["L"]=FFP_LOAD_DATE.map(lambda x:x/np.timedelta64(30*24*60,"m"))
    df2["R"]=data_set["LAST_TO_END"]
    df2["F"]=data_set["FLIGHT_COUNT"]
    df2["M"]=data_set["SEG_KM_SUM"]
    df2["C"]=data_set["avg_discount"]
    df3=df2[["L","R","F","M","C"]]
    return df3

df3=STRCTURE_LRFMC(df)
df3.head()

经过如上处理的数据:

5个指标的取值范围差异较大,需进行标准化处理,消除数量级的影响;

# 数据标准化
def zscore_data(data):
    data2=(data-data.mean(axis=0))/data.std(axis=0)
    data2.columns=["Z"+i for i in data.columns]
    return data2

df4=zscore_data(df3)
df4.head()

经过上述的处理,我们就可以用上面的数据进行建立模型了。





模型构建




1、K-means聚类

采用K-Means算法对客户数据进行客户分群,聚成五类(需结合业务的理解与分析来确定客户的类别数量)

k=5
# 调用k-means算法
model = KMeans(n_clusters=k, init='random',random_state=28,n_jobs=4)  
# 输入聚类类别数目,n_jobs为并行数
#n_clusters就是K值,也是聚类值
#init初始化方法,可以是kmeans++,随机,或者自定义的ndarray
model.fit(df4)  # 训练

# 训练结果如下:
KMeans(algorithm=
'auto', copy_x=True, init='k-means++', max_iter=300,
       n_clusters=
5, n_init=10, n_jobs=1, precompute_distances='auto',
       random_state=None, tol=
0.0001, verbose=0)

K-Means算法的API以及实例可以参考sklearn官网:


#  model.cluster_centers_ 聚类中心
#  labels = model.labels_ 每个样本对应的簇类别标签
r1 = pd.Series(model.labels_).value_counts()  # 统计各个类别的数目
r2 = pd.DataFrame(model.cluster_centers_)  # 找出聚类中心
r = pd.concat([r2, r1], axis=1)   # 得到聚类中心对应的类别下的数目
r.columns = list(df4.columns) + [u'类别数目']  # 重命名表头
r.to_excel('../客户价值识别/KMeansNum.xls')

r3 = pd.concat([df4, pd.Series(model.labels_, index=df4.index)], axis=1)   # 详细输出每个样本对应的类别
r3.columns = list(df4.columns) + [u'聚类类别']  # 重命名表头
r3.to_excel('../客户价值识别/KMeans.xls')

r为每个类别的数目,r3为每个样本聚类的类别,r和r3分别如下:

聚为几类合适?

除了业务,我们还可以通过聚类的性能进行评估:

聚类类别数和组内误方差的变化,出现“肘点”对应的类别数可以认为最优。

distortions=[]
for i in range(1,10):
    km=KMeans(n_clusters=i,init='random',random_state=28)
    #n_clusters就是K值,也是聚类值
    #init初始化方法,可以是kmeans++,随机,或者自定义的ndarray
    km.fit(df4)
    distortions.append(km.inertia_)

plt.plot(range(1,10),distortions,marker="o")
plt.xlabel("簇数量")
plt.ylabel("簇内误方差(SSE)")
plt.show()

上图可知,聚为5类,还是比较理想的。

2、图片展示

通过K-Means聚类模型的构建和训练,以及将每个观测(每个人)划分为1-5中的其中一类,并将结果保存在KMeans.xlsx文件中,但是不直观,需要我们可视化形象直观输出我们的结果,选择雷达图展示。

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 = ["客户关系长度","消费的时间间隔","总消费次数","总消费金额","平均折扣率"]
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()
plt.savefig("客户群特征分析图.jpg",dpi=200)






基于模型结果的分析应用




客户价值分析

针对“客户群特征分析图”所示的聚类结果,结合业务进行特征分析。我们重点关注的是L(户关系长度)、F(消费频率)、M(飞行里程)三个指标:

  • 客户群1:在C属性上最大,可定义为重要挽留客户;

  • 客户群2:在R属性上最大,在F、M属性上最小,可定义为低价值客户;

  • 客户群3:在F、M属性上最大,在R属性上最小,可定义为重要保持客户;

  • 客户群4:在L、C属性上最小,可定义为一般客户;

  • 客户群5:在L属性上最大,可定义为重要发展客户;

客户群价值排名

  • 重要保持客户:C(平均折扣率较高、仓位等级较高)、F(乘坐次数)、M(里程)较高,R(最近乘坐航班)低。应将资源优先投放到这类客户身上,进行差异化管理,提高客户的忠诚度和满意度。

  • 重要发展客户:C较高,R、F、M较低。这类客户入会时长(L)短、当前价值低、发展潜力大,应促使客户增加在本公司和合作伙伴处的消费。

  • 重要挽留客户:C、F 或 M 较高,R较高 或 L变小,客户价值变化的不确定性高。应掌握客户最新信息、维持与客户的互动。

  • 一般和低价值客户:C、F、M、L低、R较高。这类客户可能在打折促销时才会选择消费。

应用

差异化管理、精准营销,提高客户忠诚度、满意度,延长客户高水平消费。

1)会员升级与保级(积分削减等)

在会员升级或保级评价的时间点前,对接近但尚未达到要求的较高消费客户进行提醒或促销活动,提高客户满意度。

2)首次兑换

对接近但尚未达到标准的会员进行提醒或促销活动,提高客户满意度。

3)交叉销售

通过与非航空类企业的合作,使客户在其他消费过程中获得本公司积分,增强与公司联系,提高忠诚度


对本文感兴趣,涉及的数据集,可以找我要。

或者关注公众号,后台回复“客户价值分析”获取。


The End







往期精选

- My Best For You -






1、Python数据分析综合小练习:销售数据分析

2、Python数据挖掘实战项目:Kaggle Titanic生存预测(EDA数据探索分析篇)

3、Pandas综合案例:超市营业额数据实战分析

4、综合实战案例——用户消费行为分析





ywq885889


感谢你能耐心读完本文,觉得对你有帮助,请扫描二维码关注或者转发,后续会持续更新更多实战化的数据分析和数据挖掘,以免错过!



    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存