7.1 背景与挖掘目标
目标:
- 借助航空公司客户数据,对客户进行分类
- 对不同的客户类别进行特征分析,比较不同类客户的客户价值
- 对不同价值的客户类别提供个性化服务,制定相应的营销策略
7.2 分析方法与过程
识别客户价值应用最广泛的模型是通过3个指标,来进行客户细分,识别出高价值的客户,简称RFM模型。
- 最近消费时间间隔(Recency)
- 消费频率(Frequency)
- 消费金额(Monetary)
在RFM模型中,消费金额表示在一段时间内,客户购买该企业产品金额的总和。由于航空票价受到运输距离、舱位等级等多种因素,同样消费金额的不同旅客对航空公司的价值是不同的。例如,一位购买长航线、低等级舱位的旅客与一位购买短航线、高等级舱位票的旅客相比,后者对于航空公司而言价值可能更高。因此,这个指标并不适用于航空公司的客户价值分析。
我们选择客户在一定时间内累积的飞行里程M和客户在一定时间内乘坐舱位所对应的折扣系数的平均值C两个指标代替消费金融。此外,考虑航空公司会员入会时间的长短在一定程度上能够影响客户价值,所以在模型中增加客户关系长度L,作为区分客户的另一指标。
航空公司LRFMC模型
模型 | L | R | F | M | C |
---|---|---|---|---|---|
航空公司LRFMC模型 | 会员入会时间距观测窗口结束的月数 | 客户最近一次乘坐公司飞机距观测窗口结束的月数 | 客户在观测窗口内乘坐公司飞机的次数 | 客户在观测窗口内累计的飞行里程 | 客户在观测窗口内乘坐舱位对应的折扣系数的平均值 |
本案例采用聚类的方法识别客户价值,通过对这5个指标进行K-Means聚类,识别出最有价值客户。
本案例航空客户价值分析的总体流程如图所示:
航空客运信息挖掘主要包括以下步骤:
- 从航空公司的数据源中进行选择性抽取与新增数据抽取分别形成历史数据和增量数据
- 数据探索分析与预处理
- 基于LRFMC模型进行客户分群,对各个客户群体进行特征分析,识别出有价值的用户
- 针对模型结果得到不同价值的客户,采用不同的营销手段,提供定制化的服务
7.2.1 数据抽取
以2014-03-31为结束时间,选取宽度为两年的时间段作为分析观测窗口,抽取观测窗口内有乘机记录的所以客户的详细数据形成历史数据。
对于后续新增的客户详细信息,以后续新增数据中最新的时间点作为结束时间,采用上述同样的方法进行抽取,形成增量数据。
7.2.2 数据探索分析
#探索分析
#返回缺失值个数以及最大最小值import pandas as pddatafile = 'G:/Python数据分析与挖掘实战/chapter7/demo/data/air_data.csv' #原始数据,第一行为属性标签
resultfile = 'G:/Python数据分析与挖掘实战/chapter7/zl/explore.xls' #数据探索结果表data = pd.read_csv(datafile, encoding='utf-8')
explore = data.describe(percentiles=[], include='all').T #转置后方便查阅
explore.head()
可以看出大致情况,接着做更详细的分析:
explore['null'] = len(data) - explore['count'] #describe()函数自动计算非空值数,需要手动计算空值数
explore = explore[['null', 'max', 'min']] #只选取部分探索结果
explore.columns = ['空值数','最大值','最小值'] #表头重命名
explore.head()
explore.to_excel(resultfile) #导出结果
通过对数据观察发现原始数据中存在票价为空值,票价最小值为0,折扣率最小值为0,总飞行公里数大于0的记录。票价为空值的数据可能是客户不存在乘机记录造成,其他数据可能是客户乘坐0折机票或者积分兑换产生的。
7.2.3 数据预处理
1.数据清洗
通过数据探索分析,发现数据中存在缺失值,票价最小值为0、折扣率最小值为0、总飞行里程数大于0的记录。由于删除后数据量为62044,异常样本数据所占比例较小,对于问题影响不大,因此对其进行丢弃处理。
- 丢弃票价为空的记录
- 丢弃票价为0、平均折扣率不为0、总飞行里程数大于0的记录
#数据清洗
import pandas as pd
datafile = 'G:/Python数据分析与挖掘实战/chapter7/demo/data/air_data.csv'
cleanedfile = 'G:/Python数据分析与挖掘实战/chapter7/zl/data_cleaned.xls' #数据清洗后保存的文件data = pd.read_csv(datafile, encoding='utf-8')
data = data[data['SUM_YR_1'].notnull()&data['SUM_YR_2'].notnull()] #票价非空值才保留
#只保留票价非零的,或者平均折扣率与总飞行里程数同时为0的记录
index1 = data['SUM_YR_1'] != 0
index2 = data['SUM_YR_2'] != 0
index3 = (data['SEG_KM_SUM'] == 0) & (data['avg_discount'] == 0)
data = data[index1 | index2 | index3] #该规则是"或"
data.to_excel(cleanedfile)#导出结果(数据集较大)
data.shape输出结果:
(62044, 44)
2.属性规约
原始数据中属性太多,根据航空公司客户价值LRFMC模型,选择与LRFMC指标相关的6个属性:FFP_DATE、LOAD_TIME、FLIGHT_COUNT、AVG_DISCOUNT、SEG_KM_SUM、LAST_TO_END。删除与其不相关、弱相关或冗余的属性。
#属性规约
filter_data = data[['FFP_DATE','LOAD_TIME','FLIGHT_COUNT','avg_discount','SEG_KM_SUM','LAST_TO_END']]
filter_data.head()
3.数据变换
- 属性构造
(1)L = LOAD_TIME - FFP_DATE(入会时间 = 观测窗口的结束时间 - 入会时间)
(2)R = LAST_TO_END(客户最近一次乘坐公司飞机距观测窗口期结束的月数 = 最后一次乘机时间至观测窗口末端时长)
(3)F = FLIGHT_COUNT(飞行次数)
(4)M = SEG_KM_SUM(总飞行公里数)
(5)C = avg_discount(平均折扣率)
from datetime import datetime
#转化成datetime格式,才能加减
filter_data = filter_data.copy()
filter_data['FFP_DATE_1'] = filter_data['FFP_DATE'].apply(lambda x : datetime.strptime(x, '%Y/%m/%d'))
filter_data['LOAD_TIME_1'] = filter_data['LOAD_TIME'].apply(lambda x : datetime.strptime(x, '%Y/%m/%d'))#格式转化
def interval_time(dd):return dd.days/30
filter_data['L'] = (filter_data['LOAD_TIME_1'] - filter_data['FFP_DATE_1']).apply(interval_time)
filter_data.head()
filter_data = filter_data.rename(columns={'LAST_TO_END':'R', 'FLIGHT_COUNT':'F', 'SEG_KM_SUM':'M', 'avg_discount':'C'})
filter_data.head()
提取LRFMC五个指标,并保存到本地:
#挑选指定列,LRFMC模型
data_selected = filter_data[['L','R','F','M','C']]data_slc = 'G:/Python数据分析与挖掘实战/chapter7/zl/data_selected.xlsx'
data_selected.to_excel(data_slc)
data_selected.describe()
从上图可以看出,5个指标的取值范围数据差异较大,为了消除数量级数据带来的影响,需要对数据进行标准化处理。
#标准化处理
data_zscored = 'G:/Python数据分析与挖掘实战/chapter7/zl/data_zscored.xlsx'
data_z = (data_selected - data_selected.mean(axis=0)) / (data_selected.std(axis=0))
data_z.columns = ['Z' + i for i in data_selected.columns] #表头重命名
data_z.head()
data_z.to_excel(data_zscored, index=False) #数据写入
7.2.4 模型构建
客户价值分析模型构建主要包括:
- 根据5个指标的数据,对客户进行聚类分群
- 结合业务对每个客户群进行特征分析,分析其客户价值,并对每个客户群进行排名
- 客户聚类
采用K-Means
聚类算法对客户数据进行客户分群,聚成5类(需要结合业务的理解与分析来确定客户的类别数量)
#K-Means聚类
from sklearn.cluster import KMeans
k = 5 #分为5类
kmodel = KMeans(n_clusters=k, n_jobs=4) #封装,n_jobs是并行数,一般等于CPU较好
kmodel.fit(data_z) #训练模型kmodel.cluster_centers_ #查看聚类中心
kmodel.labels_ #查看各样本对应的类别#简单打印结果
s = pd.Series(['客户群1','客户群2','客户群3','客户群4','客户群5'], index=[0,1,2,3,4])
r1 = pd.Series(kmodel.labels_).value_counts() #统计各个类别的数目
r2 = pd.DataFrame(kmodel.cluster_centers_ ) #找出聚类中心
r = pd.concat([s,r1,r2],axis=1) #横向连接,0是纵向连接
r.columns =[u'聚类名称'] +[u'聚类个数'] + list(data_z.columns) #重命名表头
r
- 客户价值分析
#客户价值分析
#代码来自 https://blog.csdn.net/Just_youHG/article/details/83904618
import numpy as np
import matplotlib.pyplot as plt
%matplotlib
#中文和负号的正常显示
plt.rcParams['font.sans-serif'] = 'Microsoft YaHei'
plt.rcParams['axes.unicode_minus'] = Falsekinds = r.iloc[:,0] #第一列:客户群
labels = r.iloc[:, 2:].columns #取到标签:ZL,ZR,ZF,ZM,ZC
centers = pd.concat([r.iloc[:, 2:], r.iloc[:,2]], axis=1) #封闭起来
centers = np.array(centers)n = len(labels)
angles = np.linspace(0, 2*np.pi, n, endpoint=False) #将一个圆划分为5块
angles = np.concatenate((angles, [angles[0]])) #使雷达图封闭起来fig = plt.figure()
ax = fig.add_subplot(111, polar=True) #设置坐标为极坐标#画若干个五边形
floor = np.floor(centers.min()) #大于最小值的最大整数
ceil = np.ceil(centers.max()) #小于最大值的最小整数
for i in np.arange(floor, ceil+0.5, 0.5):ax.plot(angles, [i] * (n+1), '--', lw=0.5, color='black')#画不同客户群的分割线
for i in range(n):ax.plot([angles[i], angles[i]], [floor, ceil], '-', lw=0.5, color='black')
#画不同的客户群所占的大小
for i in range(len(kinds)):ax.plot(angles, centers[i], lw=2, label=kinds[i])#ax.fill(angles, centers[i])ax.set_thetagrids(angles * 180 / np.pi, labels) # 设置显示的角度,将弧度转换为角度
plt.legend(loc='lower right', bbox_to_anchor=(1.5, 0.0)) # 设置图例的位置,在画布外#美化
ax.set_theta_zero_location('N' )# 设置极坐标的起点(即0°)在正北方向,即相当于坐标轴逆时针旋转90°
ax.spines['polar'].set_visible(False) # 不显示极坐标最外圈的圆
ax.grid(False) # 不显示默认的分割线
ax.set_yticks([]) # 不显示坐标间隔
plt.show()
针对聚类结果进行特征分析:
- 客户群1在R属性上最大,在F、M属性上最小
- 客户群2在F、M属性上最大,在R属性上最小
- 客户群3在C属性上最大
- 客户群4在L、C属性上最小
- 客户群5在L属性上最大
客户群体特征描述表:
由上述特征分析的图标说明每个客户群都有显著不同的表现特征,基于该特征描述,定义五个级别的客户类别:
客户群 | 排名 | 排名含义 | 人数 |
---|---|---|---|
客户群2 | 1 | 重要保持客户 | 5337 |
客户群3 | 2 | 重要发展客户 | 4216 |
客户群5 | 3 | 重要挽留客户 | 12118 |
客户群4 | 4 | 一般客户 | 24638 |
客户群1 | 5 | 低价值客户 | 15735 |
特征分析:
- 重要保持客户:这类客户平均折扣率(C)较高(一般所乘航班的舱位等级较高),最近乘坐过本公司航班(R)低,乘坐的次数(F)或里程(M)较高。他们是航空公司的高价值客户,是最为理想的客户类型,对航空公司的贡献最大,所占比例却较小。航空公司应该优先将资源投放到他们身上,对他们进行差异化管理和一对一营销,提高这类客户的忠诚度与满意度,尽可能延长这类客户的高水平消费。
- 重要发展客户:这类客户平均折扣率(C)较高,最近乘坐本公司航班(R)低,但乘坐次数(F)或乘坐里程(M)较低。这类客户入会时长(L)短,他们是航空公司的潜在价值客户。虽然这类客户的当前价值并不是很高,但却有很大的发展潜力。航空公司要努力促使这类客户增加在本公司的乘机消费和合作伙伴处的消费,也就是增加客户的钱包份额。通过客户价值的提升,加强这类客户的满意度,提高他们转向竞争对手的转移成本,使他们逐渐成为公司的忠诚客户。
- 重要挽留客户:这类客户过去所乘坐航班的平均折旧率(C)、乘坐次数(F)或里程(M)较高,但是较长时间,但是较长时间已经没有乘坐本公司的航班®高或是乘坐频率变小。他们客户价值变化的不确定性很高。由于这些客户衰退的原因各不相同,所以掌握客户的最新信息、维持与客户的互动就显得尤为重要。航空公司应该根据这些客户的最近消费时间、消费次数的变化情况,推测客户消费的异动状况,并列出客户名单,对其重要联系,采取一定的营销手段,延长客户的生命周期。
- 一般与低价值客户:这类客户所乘航班的平均折扣率(C)很低,较长时间没有乘坐过本公司航班(R)高,乘坐的次数(F)或里程(M)较低,入会时长(L)短。他们是航空公司的一般用户与低价值客户,可能是在航空公司机票打折促销时,才会乘坐本公司航班。
7.3 模型应用
- 会员的升级与保级
- 首次兑换
- 交叉销售