1. 背景与挖掘目标

客户关系管理的关键问题是客户分类,通过客户分类,区分无价值客户、高价值客户,企业针对不同价值得客户制定优化个性化服务方案,采取不同营销策略,将有限营销资源集中于高价值客户,实现企业利润最大化目标。

航空公司采集了大量会员档案信息和其乘坐航班记录,经过加工获得了以下部分数据样例:

hadoop航空公司客户价值分析大数据项目 航空公司目标客户_Python

完整详细的数据见  ....\chapter7\demo\data\air_data.csv

我们的挖掘目标是:

1)借助航空公司的客户数据,对客户进行分类。

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

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

2. 分析方法与过程

本案例的目标是客户价值识别,识别客户价值应用最广泛的模型是通过3个指标来进行客户细分:

1)最近消费时间间隔(Recency)

2)消费频率(Frequency)

3)消费金额(Monetary)

简称RFM模型。

在FRM模型中,消费金额(Monetary)表示在一段时间内,客户购买该企业产品金额的总和。由于航空票价受到运输距离、舱位等级等多种因素的影响,同样消费金额的不同旅客对航空公司的价值是不同的。例如,一位购买长航线、低等级舱位票的旅客与一位购买短航线、高等级舱位票的旅客相比,后者对于航空公司而言价值可能更高。因此这个指标并不适用于航空公司的客户价值分析。我们选择客户在一定时间内积累的飞行里程M和客户字一定时间内乘坐舱位所对应的折扣系数的平均值C两个指标代替消费金额。此外,考虑航空公司会员入会时间的长短在一定程度上能够影响客户价值,所以在模型中增加客户关系长度L,作为区分客户的另一个指标。

本案例将客户关系长度L、消费时间间隔R、消费频率F、飞行里程M和折扣系数的平均值C五个指标作为航空公司识别客户价值指标,记为LRFMC模型。

hadoop航空公司客户价值分析大数据项目 航空公司目标客户_DM_02

针对航空公司LRFMC模型,如果采用传统的RFM模型分析的属性分箱方法(如下图),虽然也能够识别出最有价值客户,但是细分的客户群太多(如下图所示,有8个客户群),提供了针对营销的成本。因此,本案例采用聚类的方法识别客户价值。通过对航空公司客户价值LRFMC模型的五个指标进行K-Means聚类,识别出最有价值客户。

hadoop航空公司客户价值分析大数据项目 航空公司目标客户_数据_03

本案例航空客户价值分析的总体流程如下图所示:

hadoop航空公司客户价值分析大数据项目 航空公司目标客户_数据_04

航空客运信息挖掘主要包括以下步骤:

1)从航空公司的数据源中进行选择性抽取与新增数据抽取分别形成历史数据和增量数据。

2)对步骤1)中形成的两个数据集进行数据探索分析与预处理,包括数据缺失值与异常值的探索分析,数据的属性规约、清洗和变换。

3)利用步骤2)中形成的已完成数据预处理的建模数据,基于旅客价值LRFMC模型进行客户分群,对各个客户群进行特征分析,识别出有价值得客户。

4)针对模型结果得到不同价值得客户,采用不同的营销手段,提供定制化的服务。

2.1 数据抽取

以2014-03-31为结束时间,选取宽度为两年的时间段作为分析观测窗口,抽取观测窗口内有乘机记录的所有客户的详细数据形成历史数据。对于后续新增的客户详细信息,以后续新增数据中最新的时间点作为结束时间,采取上述同样的方法进行抽取,形成增量数据。

从航空公司系统内部的客户基本信息、乘机信息以及积分信息等详细数据中,根据末次飞行日期(LAST_FLIGHT_DATE),抽取2012-04-01至2014-03-31内所有乘客的详细数据,总共有62988条记录。其中包含了会员卡号入会时间、性别、年龄、会员卡级别、工作地城市、工作地所在省份、工作地所在国家、观测窗口结束时间、观测窗口乘机积分、飞行公里数、飞行次数、飞行时间、乘机时间间隔和平均折扣率等44个属性。

2.2 数据探索分析

本案例的探索分析是对数据进行缺失值分析与异常值分析,分析出数据的规律以及异常值。查找每列属性观测值中空值个数、最大值、最小值得Python代码如下所示:

#-*- coding: utf-8 -*-
#对数据进行基本的探索
#返回缺失值个数以及最大最小值

import pandas as pd 

datafile = 'D:/Python DS DM/chapter7/demo/data/air_data.csv'
resultfile = 'D:/Python DS DM/practice code/chp07/tmp/explore.xls' #数据探索结果输出的文件

data = pd.read_csv(datafile,encoding='utf-8') #读取原始数据,指定UTF-8编码
explore = data.describe(percentiles=[],include = 'all').T
#percentiles: 是一个列表,分位数,默认是[.25, .5, .75]
#include: 包含在结果中的数据类型白名单
#.T转置的目的是为了便于查阅
# describe()函数的返回类型:Series/DataFrame of summary statistics
explore['null'] = len(data)-explore['count'] 
#len(data)是样本数目(单个数),
#explore['count']是返回一个Series列向量,向量的每一个元素代表每一个属性的非空数目
#explore['null'] 也是一个Series,每一个元素代表每个属性的空值数目
#本来explore中不存在null这一列属性,explore['null']加上去了
explore = explore[['null','max','min']] #只取三个属性
explore.columns = [u'空值数',u'最大值',u'最小值']  #表头重命名

'''这里只选取部分探索结果。
describe()函数自动计算的字段有count(非空值数)、
unique(唯一值数)、top(频数最高者)、freq(最高频数)、
mean(平均值)、std(方差)、min(最小值)、50%(中位数)、max(最大值)'''

explore.to_excel(resultfile) #导出探索的结果

探索结果数据详细见: '....\chapter7\demo\tmp\explore.xls'

2.3 数据预处理

1.数据清洗

通过数据探索发现,发现数据中存在缺失值,票价最小值为0、折扣率最小值为0、总飞行公里数大于0的记录。由于原始数据量大。这类数据所占比例较小,对于问题影响不大,因此对其进行丢弃处理。具体的处理方法:

1)丢弃票价位空的记录(SUM_YR)

2)丢弃票价为0、平均折扣率不为0、总飞行公里数大于0的记录(我觉得以上数据清洗的结果不能看出这个结论)

使用pandas对满足清洗条件的数据进行丢弃,处理方法:满足清洗条件的一行数据全部丢弃。

2.属性规约

原始数据中属性太多,根据航空公司客户价值LRFMC模型,选择与LRFMC指标相关的6个属性:FFP_DATE、LOAD_TIME、FLIGHT_COUNT、AVG_DISCOUNT、SEG_KM_SUM、LAST_TO_END。删除与其不相关、弱相关或冗余的属性。经过属性选择后的数据集如下形式:

hadoop航空公司客户价值分析大数据项目 航空公司目标客户_DM_05

数据清洗和属性规约的代码如下:

#-*- coding: utf-8 -*-
#数据清洗,过滤掉不符合规则的数据-------------------------------------------------------------------

import pandas as pd
datafile = 'D:/Python DS DM/chapter7/demo/data/air_data.csv' #航空的原始数据,第一行为属性标签
cleanedfile = 'D:/Python DS DM/practice code/chp07/tmp/data_cleaned1.xls' #数据清洗后保存的文件

data = pd.read_csv(datafile,encoding='utf-8') #把数据读入到内存中,同时指定UTF-8编码

data = data[data['SUM_YR_1'].notnull() & data['SUM_YR_2'].notnull()] #两个窗口的票价同时非空值才保留?
#只保留票价非0的,或者平均折扣率与总飞行公里数同时为0的记录
index1 = data['SUM_YR_1']!=0  #返回一个Series,元素类型是布尔类型
index2 = data['SUM_YR_2']!=0
index3 = (data['SEG_KM_SUM'] == 0)&(data['avg_discount'] ==0)#返回一个Series,元素类型是布尔类型
data = data[index1 | index2 | index3]


#属性规约----------------------------------------------------------------------------------------
data = data[['LOAD_TIME','FFP_DATE','LAST_TO_END','FLIGHT_COUNT','SEG_KM_SUM','avg_discount']]

data.to_excel(cleanedfile)



3.数据变换

数据变换是将数据转换成“适当的”格式,以适应挖掘任务及算法的需求。本案例中主要采用的数据变换方式为属性构造和数据标准化。

由于原始数据中并没有直接给出LRFMC五个指标,需要通过原始数据提取这五个指标,具体的计算方式如下。

(1)L=LOAD_TIME - FFP_DATE  (L代表客户关系长度,表征会员入会时间的长短)

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

(2)R=LAST_TO_END  (R代表消费时间间隔)

客户最近一次乘坐公司飞机距观测窗口结束的月数 = 最后一次乘机时间至观测窗口末端时长     (单位:月)

(3)F =FLIGHT_COUNT  (F代表消费频率)

客户在观测窗口内乘坐公司飞机的次数 = 观测窗口的飞行次数       (单位:月)

(4)M =SEG_KM_SUM    (M飞行里程数)

客户在观测时间内在公司累计飞行里程 = 观测窗口的总飞行公里数    (单位:月)

(5)C=avg_discount   (C代表折扣系数的平均值)

客户在观测时间内乘坐舱位所对应的折扣系数的平均值 = 平均折扣率    (单位:月)

属性构造的代码如下:

#-*- coding: utf-8 -*-
import pandas as pd
import numpy as np

datafile = 'D:/Python DS DM/practice code/chp07/tmp/data_cleaned1.xls'  #只经过数据清洗和属性规约的数据
acfile = 'D:/Python DS DM/practice code/chp07/tmp/data_attribute_construction.xls' #属性构造后的输出文件

data = pd.read_excel(datafile) #读入内存

d_ffp=pd.to_datetime(data['FFP_DATE'])  #转换成为DateTime数据类型
d_load=pd.to_datetime(data['LOAD_TIME']) #由于输入是series,返回Series of datetime64 dtype[ns]
res=d_load-d_ffp #这个单位是’天‘,下面还得转换成’月‘  看一下res的数据类型,发现是timedelta64[ns]
data['L']=res.map(lambda x:x/np.timedelta64(30*24*60,'m'))
#map()是Python内置的高阶函数,它接收一个函数和一个序列,根据提供的函数对指定序列做映射。
#lambda  行内自定义的函数,用来映射序列res
#np.timedelta64(30*24*60,'m'):    这个没太明白

data['R'] = data['LAST_TO_END']
data['F'] = data['FLIGHT_COUNT']
data['M'] = data['SEG_KM_SUM']
data['C'] = data['avg_discount']

data = data[['L','R','F','M','C']]

data.to_excel(acfile)

5个指标的数据提取后,对每个指标数据分布情况进行分析,其数据的取值范围如下:

hadoop航空公司客户价值分析大数据项目 航空公司目标客户_DM_06

从表中可以看出,5个指标的取值范围数据差异较大,为了消除数量级数据带来的影响,需要对数据进行标准化处理。代码如下:

#-*- coding: utf-8 -*-

import pandas as pd

datafile = 'D:/Python DS DM/practice code/chp07/tmp/data_attribute_construction.xls'
zscoredfile = 'D:/Python DS DM/practice code/chp07/tmp/zscoreddata.xls'

#标准化处理
data = pd.read_excel(datafile)
data = (data-data.mean(axis=0))/(data.std(axis=0)) #axis =0 跨行操作,一整列
# .mean() 返回一个series,DataFrame和Series之间的运算是传播操作
data.columns=['Z'+i for i in data.columns] #表头重命名

data.to_excel(zscoredfile,index = False) #数据写出,不要index

标准化处理后的数据集大致如下图所示:

hadoop航空公司客户价值分析大数据项目 航空公司目标客户_DM_07

2.4 模型构建

客户价值分析模型构建主要由两个部分构成,第一部分根据航空公司客户5个指标的数据,对客户进行聚类分群。第二部分结合业务对每个客户进行特征分析,分析其客户价值,并对每个客户群进行排名。

1. 客户聚类

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

#-*- coding: utf-8 -*-
#K-Means聚类算法

import pandas as pd
from sklearn.cluster import KMeans #导入k均值聚类算法函数

inputfile = 'D:/Python DS DM/practice code/chp07/tmp/zscoreddata.xls'  #这是待聚类的训练数据
k=5  #指定需要聚类的类别数

data = pd.read_excel(inputfile)  #将数据读入内存

#调用K-means算法,进行聚类分析
kmodel = KMeans(n_clusters = k) #构建聚类模型,n_jobs是并行数,一般等于CPU数比较好
kmodel.fit(data)   #训练模型

print kmodel.cluster_centers_   #查看聚类中心
print kmodel.labels_      #查看各样本对应的类别

运行结果如下

hadoop航空公司客户价值分析大数据项目 航空公司目标客户_DM_08

2.客户价值分析

针对聚类结果进行特征分析,如下图所示,其中:

客户群1:在F、M属性上最大,在R属性上最小。

客户群2:在L属性上最大。

客户群3:在R属性上最大,在F、M属性上最小。

客户群4:在L、C属性上最小。

客户群5:在C属性上最大。


hadoop航空公司客户价值分析大数据项目 航空公司目标客户_Python_09

绘图代码:

#画出特征雷达图,代码接KMeans_cluster.py------------------------------------------------------
#-*- coding: utf-8 -*-

import numpy as np
import matplotlib.pyplot as plt

labels = data.columns   #标签
k = 5     #数据个数
plot_data = kmodel.cluster_centers_ 
color = ['b', 'g', 'r', 'c', 'y'] #指定颜色

angles = np.linspace(0, 2*np.pi, k, endpoint=False) 
#np.linspace函数:生成一个等差数列,用来当做角度,endpoint=False不包含终值2pi
#这个角度应该是五角星图五个轴的角度分布
plot_data = np.concatenate((plot_data, plot_data[:,[0]]), axis=1) # 闭合
#np.concatenate函数: 将两个array数组进行拼接,axis=1说明是跨列 水平方向的拼接
#拼接后的数据类似下面,第一列和最后一列的数据相同
'''
[[-0.31321639  1.68682327 -0.57391382 -0.5367476  -0.17484976 -0.31321639]
 [-0.70030802 -0.41503955 -0.16081343 -0.16052895 -0.25734436 -0.70030802]
 [ 0.4836574  -0.79940021  2.4831749   2.42445945  0.30923797  0.4836574 ]
 [ 0.04421627 -0.00258413 -0.23043928 -0.23494195  2.17504264  0.04421627]
 [ 1.16081445 -0.37743605 -0.0866912  -0.09460942 -0.15676924  1.16081445]]
'''
angles = np.concatenate((angles, [angles[0]])) # 闭合
#array([0. , 1.25663706 , 2.51327412 , 3.76991118 , 5.02654825 , 0.])

fig = plt.figure() #生成一块绘图布
ax = fig.add_subplot(111, polar=True) #polar参数  雷达图极坐标
for i in range(len(plot_data)):
  ax.plot(angles, plot_data[i], 'o-', color = color[i], label = u'客户群'+str(i), linewidth=2)# 画线,每行没一个客户群
  
ax.set_rgrids(np.arange(0.01, 3.5, 0.5), np.arange(-1, 2.5, 0.5), fontproperties="SimHei") #设置网格的坐标
ax.set_thetagrids(angles * 180/np.pi, labels, fontproperties="SimHei") #设置网格的角度
plt.legend(loc = 4)
plt.show()

结合业务分析,通过比较各个指标在群间的大小对某一个群的特征进行评价分析。例如客户群1在F、M属性最大,在R指标最小,因此可以说F、M、R是客户群1的优势特征。以此类推,F、M、R是客户群3上的劣势特征,从而总结出每个群的优势和劣势特征。

hadoop航空公司客户价值分析大数据项目 航空公司目标客户_Python_10

以下再结合具体的特征定义五个等级的客户类别,针对不同等级的客户,采取相应的营销手段和策略,为航空公司的价值客户群管理提供参考(既业务分析)。