航空公司客户价值分析
企业在面向客户制定运营策略、营销策略时,希望能够针对不同的客户推行不同的策略,实现精准化运营,以期获取最大的转化率。客户关系管理是精准化运营的基础,而客户关系管理的核心是客户分类。通过客户分类,对客户群体进行细分,区别出低价值客户与高价值客户,对不同的客户群体开展不同的个性化服务,将有限的资源合理地分配给不同价值的客户,从而实现效益最大化。
本章将使用航空公司客户数据,结合RFM模型,采用K-Means聚类算法,对客户进行分群,比较不同类别客户的价值,从而制定相应的营销策略。
1 背景与挖掘目标
信息时代的来临使得企业营销的焦点从产品中心转变为客户中心,客户关系管理成为企业的核心问题。客户关系管理的关键问题是客户分类,通过客户分类,区分无价值客户与高价值客户,针对不同价值的客户制定个性化服务方案,采取不同营销策略,将有限的营销资源集中于高价值客户,以实现企业利润最大化目标。准确的客户分类结果是企业优化营销资源分配的重要依据,客户分类逐渐成为客户关系管理中亟待解决的关键问题之一。
面对激烈的市场竞争,各个航空公司相继推出了更优惠的营销方式来吸引更多的客户,国内某航空公司面临着常旅客流失、竞争力下降和航空资源未充分利用等经营危机。通过建立合理的客户价值评估模型,对客户进行分类,分析比较不同客户群体的值,并制定相应的营销策略,对不同的客户群提供个性化的客户服务是必须的和有效的。结合该航空公司已积累的大量的会员档案信息和其乘坐航班记录,实现以下目标:
1)借助航空公司客户数据,对客户进行分类。
2)对不同的客户类别进行特征分析,比较不同类别的客户的价值。
3)针对不同价值的客户类别制定相应的营销策略,为其提供个性化服务。
2.分析方法与过程
全球经济环境和市场环境已经悄然改变,企业的业务逐步从以产品为主导转向以客户需求为主导。一种全新的“以客户为中心”的业务模式正在形成并被提升到前所未有的高度。然而与客户保持良好的关系需要花费成本,企业所拥有的客户中只有一部分能为企业带来利润。企业的资源也是有限的,忽视高潜力的客户而对所有客户都提供同样的服务,将无法使企业的资源发挥其最大效用去创造最大化的利润。任何企业要想生存和发展,都必须获得利润。追求利润最大化是企业生存和发展的宗旨之一。所以企业不可能也不应该和所有的客户都保持同样的关系。客户营销战略的倡导者Jay & Adam Curry从国外数百家公司进行的客户营销实施经验中提炼了如下经验:
1)公司收入的80%来自顶端20%客户。
2)20%的客户其利润率为100%。
3)90%以上的收入来自现有客户。
4)大部分的营销预算经常被用在非现有客户上。
5)5%至30%的客户在客户金字塔中具有升级潜力。
6)客户金字塔中客户升级2%,意味着销售收入增加10%,利润增加50%。
这些经验也许并不完全准确,但它揭示了新时代客户分化的趋势,也说明了对客户价值分析的迫切性和必要性。如果把客户的盈利性加以分析,就会发现客户盈利结构已经发生了重大变化,只有特定的一部分客户给企业带来了利润。企业如果想获得长期发展,必须对这类客户做到有效的识别和管理。如果用同样的方法应对所有与企业有业务往来的客户,必然不会获得成功。
众多的企业管理者虽然知道客户价值分析的重要性,但对如何进行客户价值分析却知之甚少。如何全方位、多角度地考虑客户价值因素,进行有效的客户价值分析,这是所有企业需要认真思索的一个问题。只有甄选出有价值的客户,并将精力集中在这些客户身上,才能有效地提升企业的竞争力,使企业获得更大的发展。
在客户价值分析领域,最具影响力并得到实证检验的理论与模型有:客户终生价值理论、客户价值金字塔模型、策略评估矩阵分析法和RFM客户价值分析模型等。
2.1 分析步骤与流程
航空公司客户价值分析案例的总体流程如图7-1所示,主要包括以下4个步骤:
1)抽取航空公司2012年4月1日至2014年3月31日的数据。
2)对抽取的数据进行数据探索分析与预处理,包括数据缺失值与异常值的探索分析、数据清洗、特征构建、标准化等操作。
3)基于RFM模型,使用K-Means算法进行客户分群。
4)针对模型结果得到不同价值的客户,采用不同的营销手段,提供定制化的服务。

图1 航空客运数据分析建模总体流程
2.2 数据探索分析
根据航空公司系统内的客户基本信息、乘机信息以及积分信息等详细数据,依据末次飞行日期(LAST_FLIGHT_DATE),以2014年3月31日为结束时间,选取宽度为两年的时间段作为分析观测窗口,抽取观测窗口2012年4月1日至2014年3月31日内有乘机记录的所有客户的详细数据形成历史数据,总共62988条记录。其中包含了会员卡号、入会时间、性别、年龄、会员卡级别、工作地城市、工作地所在省份、工作地所在国家、观测窗口结束时间、观测窗口乘机积分、飞行公里数、飞行次数、飞行时间、乘机时间间隔、平均折扣率等44个属性,如表1所示。
表1 航空公司数据属性说明

2.2.1 描述性统计分析
通过对原始数据观察发现数据中存在票价为空值的记录,同时存在票价最小值为0、折扣率最小值为0但总飞行公里数大于0的记录。票价为空值的数据可能是客户不存在乘机记录造成的。其他的数据可能是客户乘坐0折机票或者积分兑换造成的。
查找每列属性观测值中空值个数、最大值、最小值,如代码清单7-1所示。
代码清单7-1 数据探索
# 对数据进行基本的探索 # 返回缺失值个数以及最大、最小值 import pandas as pd datafile= '../data/air_data.csv' # 航空原始数据,第一行为属性标签 resultfile = '../tmp/explore.csv' # 数据探索结果表 # 读取原始数据,指定UTF-8编码(需要用文本编辑器将数据转换为UTF-8编码) data = pd.read_csv(datafile, encoding = 'utf-8') # 包括对数据的基本描述,percentiles参数是指定计算多少的分位数表(如1/4分位数、中位数等) explore = data.describe(percentiles = [], include = 'all').T # describe()函数自动计算非空值数,需要手动计算空值数 explore['null'] = len(data)-explore['count'] explore = explore[['null', 'max', 'min']] explore.columns = [u'空值数', u'最大值', u'最小值'] # 表头重命名 ''' 这里只选取部分探索结果。 describe()函数自动计算的字段有count(非空值数)、unique(唯一值数)、top(频数最高者)、 freq(最高频数)、mean(平均值)、std(方差)、min(最小值)、50%(中位数)、max(最大值) ''' explore.to_csv(resultfile) # 导出结果 |
根据代码清单7-1得到的探索结果见表2。
表2 数据探索分析结果表

2.2.2 分布分析
分别从客户基本信息、乘机信息、积分信息3个角度进行数据探索,寻找客户信息的分布规律。
(1)客户基本信息分布分析
选取客户基本信息中的入会时间、性别、会员卡级别和年龄字段进行探索分析,探客户的基本信息分布情况,如代码清单7-2所示。
代码清单7-2 探索客户的基本信息分布情况
# 客户信息类别 # 提取会员入会年份 from datetime import datetime ffp = data['FFP_DATE'].apply(lambda x:datetime.strptime(x,'%Y/%m/%d')) ffp_year = ffp.map(lambda x : x.year) # 绘制各年份会员入会人数直方图 fig = plt.figure(figsize=(8 ,5)) # 设置画布大小 plt.rcParams['font.sans-serif'] = 'SimHei' # 设置中文显示 plt.rcParams['axes.unicode_minus'] = False plt.hist(ffp_year, bins='auto', color='#0504aa') plt.xlabel('年份') plt.ylabel('入会人数') plt.title('各年份会员入会人数') plt.show() plt.close # 提取会员不同性别人数 male = pd.value_counts(data['GENDER'])['男'] female = pd.value_counts(data['GENDER'])['女'] # 绘制会员性别比例饼图 fig = plt.figure(figsize=(7 ,4)) # 设置画布大小 plt.pie([ male, female], labels=['男','女'], colors=['lightskyblue', 'lightcoral'], autopct='%1.1f%%') plt.title('会员性别比例') plt.show() plt.close # 提取不同级别会员的人数 lv_four = pd.value_counts(data['FFP_TIER'])[4] lv_five = pd.value_counts(data['FFP_TIER'])[5] lv_six = pd.value_counts(data['FFP_TIER'])[6] # 绘制会员各级别人数条形图 fig = plt.figure(figsize=(8 ,5)) # 设置画布大小 plt.bar(x=range(3), height=[lv_four,lv_five,lv_six], width=0.4, alpha=0.8, color='skyblue') plt.xticks([index for index in range(3)], ['4','5','6']) plt.xlabel('会员等级') plt.ylabel('会员人数') plt.title('会员各级别人数') plt.show() plt.close() # 提取会员年龄 age = data['AGE'].dropna() age = age.astype('int64') # 绘制会员年龄分布箱型图 fig = plt.figure(figsize=(5 ,10)) plt.boxplot(age, patch_artist=True, labels = ['会员年龄'], # 设置x轴标题 boxprops = {'facecolor':'lightblue'}) # 设置填充颜色 plt.title('会员年龄分布箱型图') # 显示y坐标轴的底线 plt.grid(axis='y') plt.show() plt.close |
通过代码清单7-2得到各年份会员入会人数直方图,如图2所示,入会人数随年份的增长而增加,在2012年达到最高峰。

图2 各年份会员入会人数
通过代码清单7-2得到会员性别比例饼图,如图3所示,可以看出男性会员明显比女性会员多。

图3 会员性别比例
通过代码清单7-2得到会员各级别人数条形图,如图4所示,可以看出绝大部分会员为4级会员,仅有少数会员为5级会员或6级会员。

图4 会员各级别人数
得到会员年龄分布箱型图,如图7-5所示,可以看出大部分会员年龄集中在30~50岁之间,极少量的会员年龄小于20岁或高于60岁,且存在一个超过100岁的异常数据。
(2)客户乘机信息分布分析
选取最后一次乘机至结束的时长、客户乘机信息中的飞行次数、总飞行公里数进行探索分析,探索客户的乘机信息分布情况,如代码清单7-3所示。
代码清单7-3 探索客户乘机信息分布情况
lte = data['LAST_TO_END'] fc = data['FLIGHT_COUNT'] sks = data['SEG_KM_SUM'] # 绘制最后乘机至结束时长箱型图 fig = plt.figure(figsize=(5 ,8)) plt.boxplot(lte, patch_artist=True, labels = ['时长'], # 设置x轴标题 boxprops = {'facecolor':'lightblue'}) # 设置填充颜色 plt.title('会员最后乘机至结束时长分布箱型图') # 显示y坐标轴的底线 plt.grid(axis='y') plt.show() plt.close # 绘制客户飞行次数箱型图 fig = plt.figure(figsize=(5 ,8)) plt.boxplot(fc, patch_artist=True, labels = ['飞行次数'], # 设置x轴标题 boxprops = {'facecolor':'lightblue'}) # 设置填充颜色 plt.title('会员飞行次数分布箱型图') # 显示y坐标轴的底线 plt.grid(axis='y') plt.show() plt.close # 绘制客户总飞行公里数箱型图 fig = plt.figure(figsize=(5 ,10)) plt.boxplot(sks, patch_artist=True, labels = ['总飞行公里数'], # 设置x轴标题 boxprops = {'facecolor':'lightblue'}) # 设置填充颜色 plt.title('客户总飞行公里数箱型图') # 显示y坐标轴的底线 plt.grid(axis='y') plt.show() plt.close |

图5 会员年龄分布箱型图
通过代码清单7-3得到客户最后一次乘机至结束的时长、客户乘机信息中的飞行次数、总飞行公里数的箱型图如图6、图7所示。

图6 客户最后一次乘机至结束的时长箱型图

图7 客户飞行次数与总飞行公里数箱型图
根据图6,客户的入会时长主要分布在50~300区间内,另外有一部分客户群体的入会时长分布在600以上的区间,可分为两个群体。根据图7,客户的飞行次数与总飞行公里数也明显地分为两个群体,大部分客户集中在箱型图下方的箱体中,少数客户分散分布在箱体上界的上方,这部分客户很可能是高价值客户,因为其飞行次数和总飞行公里数明显超过箱体内的其他客户。
(3)客户积分信息分布分析
选取积分兑换次数、总累计积分进行探索分析,探索客户的积分信息分布情况,如代码清单7-4所示。
代码清单7-4 探索客户的积分信息分布情况
# 积分信息类别 # 提取会员积分兑换次数 ec = data['EXCHANGE_COUNT'] # 绘制会员兑换积分次数直方图 fig = plt.figure(figsize=(8 ,5)) # 设置画布大小 plt.hist(ec, bins=5, color='#0504aa') plt.xlabel('兑换次数') plt.ylabel('会员人数') plt.title('会员兑换积分次数分布直方图') plt.show() plt.close # 提取会员总累计积分 ps = data['Points_Sum'] # 绘制会员总累计积分箱型图 fig = plt.figure(figsize=(5 ,8)) plt.boxplot(ps, patch_artist=True, labels = ['总累计积分'], # 设置x轴标题 boxprops = {'facecolor':'lightblue'}) # 设置填充颜色 plt.title('客户总累计积分箱型图') # 显示y坐标轴的底线 plt.grid(axis='y') plt.show() plt.close |
通过代码清单7-4得到客户积分兑换次数直方图和总累计积分分布箱型图,分别如图8、图9所示。

图8 客户积分兑换次数直方图

图9 客户总累计积分分布箱型图
通过图8可以看出,绝大部分客户的兑换次数在0~10的区间内,这表示大部分客户都很少进行积分兑换。通过图7-9可以看出,一部分客户集中在箱体中,少部分客要明显高于箱体内的客户的积分。
(4)相关性分析
客户信息属性之间存在相关性,选取入会时间、会员卡级别、客户年龄、飞行次数、总飞行公里数、最近一次乘机至结束时长、积分兑换次数、总累计积分属性,通过相关系数矩阵与热力图分析各属性间的相关性,如代码清单7-5所示。
代码清单7-5 相关系数矩阵与热力图
# 提取属性并合并为新数据集 data_corr = data[['FFP_TIER','FLIGHT_COUNT','LAST_TO_END', 'SEG_KM_SUM','EXCHANGE_COUNT','Points_Sum']] age1 = data['AGE'].fillna(0) data_corr['AGE'] = age1.astype('int64') data_corr['ffp_year'] = ffp_year # 计算相关性矩阵 dt_corr = data_corr.corr(method='pearson') print('相关性矩阵为:\n',dt_corr) # 绘制热力图 import seaborn as sns plt.subplots(figsize=(10, 10)) # 设置画面大小 sns.heatmap(dt_corr, annot=True, vmax=1, square=True, cmap='Blues') plt.show() plt.close |
通过代码清单7-5得到相关系数矩阵如表3所示,得到热力图,如图7-10所示,可以看出部分属性间具有较强的相关性,如FLIGHT_COUNT(飞行次数)属性与SEG_KM_SUM(飞行总公里数)属性;也有部分属性与其他属性的相关性都较弱,如AGE(年龄)属性与EXCHANGE_COUNT(积分兑换次数)属性。
表3 相关系数矩阵

2.2.3 数据预处理
本案例主要采用数据清洗、属性归约与数据变换的预处理方法。
2.2.3.1 数据清洗
观察数据发现,原始数据中存在票价为空值、票价最小值为0、折扣率最小值为0、总飞行公里数大于0的记录。票价为空值的数据可能是客户不存在乘机记录造成的。其他的数据可能是客户乘坐0折机票或者积分兑换造成的。由于原始数据量大,这类数据所占比例较小,对于问题影响不大,因此对其进行丢弃处理。同时,在进行数据探索时,发现部分年龄大于100的记录,也进行丢弃处理,具体处理方法如下:

图10 热力图
1)丢弃票价为空的记录。
2)保留票价不为0的,或者平均折扣率不为0且总飞行公里数大于0的记录。
3)丢弃年龄大于100的记录。
使用pandas对满足清洗条件的数据进行丢弃,处理方法为满足清洗条件的一行数据全部丢弃,如代码清单7-6所示。
代码清单7-6 清洗空值与异常值
import numpy as np import pandas as pd datafile = '../data/air_data.csv' # 原始数据路径 cleanedfile = '../tmp/data_cleaned.csv' # 数据清洗后保存的文件路径 # 读取数据 airline_data = pd.read_csv(datafile,encoding = 'utf-8') print('原始数据的形状为:', airline_data.shape) # 去除票价为空的记录 airline_notnull = airline_data.loc[airline_data['SUM_YR_1'].notnull() & airline_data['SUM_YR_2'].notnull(),:] print('删除缺失记录后数据的形状为:', airline_notnull.shape) # 只保留票价非零的,或者平均折扣率不为0且总飞行公里数大于0的记录 index1 = airline_notnull['SUM_YR_1'] != 0 index2 = airline_notnull['SUM_YR_2'] != 0 index3 = (airline_notnull['SEG_KM_SUM']> 0) & (airline_notnull['avg_discount'] != 0) index4 = airline_notnull['AGE'] > 100 # 去除年龄大于100的记录 airline = airline_notnull[(index1 | index2) & index3 & ~index4] print('数据清洗后数据的形状为:',airline.shape) airline.to_csv(cleanedfile) # 保存清洗后的数据 |
2.2.3.2 属性归约
本案例的目标是客户价值分析,即通过航空公司客户数据识别不同价值的客户。识别客户价值应用最广泛的模型是RFM模型。
(1)RFM模型
R(Recency)
R(Recency)指的是最近一次消费时间与截止时间的间隔。通常情况下,客户最近一次消费时间与截止时间的间隔越短,对即时提供的商品或是服务也最有可能感兴趣。这也是为什么消费时间间隔0~6个月的顾客收到的沟通信息多于1年以上的顾客的原因。
最近一次消费时间与截止时间的间隔不仅能够为确定促销客户群体提供依据,还能够从中得出企业发展的趋势。如果分析报告则表示该公司是个稳步上升的公司。反之,最近一次消费时间很近的客户越来越少,则说明该公司需要找到问题所在,及时调整营销策略。
F(Frequency)
F(Frequency)指客户在某段时间内所消费的次数。可以说消费频率越高的客户,其满意度越高,其忠诚度也就越高,客户价值也就越大。增加客户购买的次数意味着从竞争对手处“偷取”市场占有率,赚取营业额。商家需要做的是通过各种营销方式,不断地去刺激客户消费,提高他们的消费频率,提升店铺的复购率。
M(Monetary)
M(Monetary)指客户在某段时间内所消费的金额。消费金额越大的顾客其消费能力自然也就越大,这就是所谓的“20%的客户贡献了80%的销售额”的二八法则。而这批客户也必然是商家在进行营销活动时需要特别照顾的群体,尤其是在商家前期资源不足的时候。不过需要注意一点:不论采用哪种营销方式,以不对客户造成骚扰为大前提,否则营销只会产生负面效果。
在RFM模型理论中,最近一次消费时间与截止时间的间隔、消费频率、消费金额是测算客户价值最重要的特征,这3个特征对营销活动具有十分重要的意义。其中,近一次消费时间与截止时间的间隔是最有力的特征。
(2)RFM模型结果解读
RFM模型包括3个特征,但无法用平面坐标系来展示,所以这里使用三维坐标系进行展示,如图7-11所示,x轴表示R特征(Recency),y轴表示F特征(Frequency),z轴表示M指标(Monetary)。每个坐标轴一般会用5级明的是R特征。在x轴上,R值越大,代表该类客户最近一次消费与截止时间的消费间隔越短,客户R维度上的质量越好。在每个轴上划分5个等级,等同于将客户划分成5×5×5=125种类型。这里划分为5级并不是严格的要求,一般是根据实际研究需求和客户的总量进行划分的,对于是否等分的问题取决于该维度上客户的分布规律。

图11 RFM客户价值模型
在图11中,左上角方框的客户RFM特征取值为155。R值是比较小的,说明该类客户最近都没有来店消费,原因可能是最近比较忙,或者对现有的产品或服务不满意或者是找到了更好的商家。R特征数值变小就需要企业管理人员引起重视,说明该类客户可能流失,会对企业造成损失。消费频率F很高,说明客户很活跃,经常到商家店里消费。消费金额M值很高,说明该类客户具备一定的消费能力,为店里贡献了很多的营业额。这类客户总体分析比较优质,但是R特征时间近度值较小,其往往是需要营销优化的客户群体。
同理,若客户RFM特征取值为555。则可以判定该客户为最优质客户,即这类客户最近到商家消费过,消费频率很高,消费金额很大。这类客户往往是企业利益的主要贡献者,需要重点关注与维护。
(3)航空公司客户价值分析的LRFMC模型
在RFM模型中,消费金额表示在一段时间内客户购买该企业产品的金额的总和。由于航空票价受到运输距离、舱位等级等多种因素的影响,同样消费金额的不同旅客对航空公司的价值是不同的,例如,一位购买长航线、低等级舱位票的旅客与一位购买短航线、高等级舱位票的旅客相比,后者对于航空公司而言更有价值。因此这个特征并不适用于航空公司的客户价值分析[1]。本案例选择客户在一定时间内累积的飞行里程M和客户在一定时间内乘坐舱位所对应的折扣系数的平均值C两个特征代替消费金额。此外,航空公司会员入会时间的长短在一定程度上能够影响客户价值,所以在模型中增加客户关系长度L,作为区分客户的另一特征。
本案例将客户关系长度L、消费时间间隔R、消费频率F、飞行里程M和折扣系数的平均值C这5个特征作为航空公司识别客户价值的特征(如表7-4所示),记为LRFMC模型。
表4 特征含义

原始数据中属性太多,根据航空公司客户价值LRFMC模型,选择与LRFMC指标相关的6个属性:FFP_DATE、LOAD_TIME、FLIGHT_COUNT、AVG_DISCOUNT、SEG_KM_SUM、LAST_TO_END。删除与其不相关、弱相关或冗余的属性,如会员卡号、性别、工作地城市、工作地所在省份、工作地所在国家、年龄等属性。属性选择的代码如代码清单7-7所示。
代码清单7-7 属性选择
import pandas as pd import numpy as np # 读取数据清洗后的数据 cleanedfile = '../tmp/data_cleaned.csv' # 数据清洗后保存的文件路径 airline = pd.read_csv(cleanedfile, encoding='utf-8') # 选取需求属性 airline_selection = airline[['FFP_DATE','LOAD_TIME','LAST_TO_END','FLIGHT_COUNT','SEG_KM_SUM','avg_discount']] print('筛选的属性前5行为:\n',airline_selection.head()) |
通过代码清单7-7得到的数据集如表5所示。
表5 属性选择后的数据集

2.2.3.3 数据变换
数据变换是将数据转换成“适当的”格式,以适应挖掘任务及算法的需要。本案例中主要采用的数据变换方式有属性构造和数据标准化。
由于原始数据中并没有直接给LRFMC 5个指标,所以需要通过原始数据提取这5个指标具体如下:
1)会员入会时间距观测窗口结束的月数L=会员入会时长,如式(7-1)所示。
![]()
2)客户最近一次乘坐公司飞机距观测窗口结束的月数R=最后一次乘机时间至观测窗口末端时长(单位:月),如式(7-2)所示。
![]()
3)客户在观测窗口内乘坐公司飞机的次数F=观测窗口的飞行次数(单位:次),如式(7-3)所示。
![]()
4)客户在观测时间内在公司累计的飞行里程M=观测窗口总飞行公里数(单位:公里),如(7-4)所示。
![]()
5)客户在观测时间内乘坐舱位所对应的折扣系数的平均值C=平均折扣率(单位:无),如式(7-5)所示。
![]()
在完成5个指标的数据提取后,对每个指标数据的分布情况进行分析,其数据的取值范围如表6所示。从表中数据可以发现,5个指标的取值范围数据差异较大,为了消除数量级数据带来的影响,需要对数据进行标准化处理。
表6 LRFMC指标取值范围

属性构造与数据标准化的代码如代码清单7-8所示。
代码清单7-8 属性构造与数据标准化
# 构造属性L L = pd.to_datetime(airline_selection['LOAD_TIME']) - \ pd.to_datetime(airline_selection['FFP_DATE']) L = L.astype('str').str.split().str[0] L = L.astype('int')/30 # 合并属性 airline_features = pd.concat([L,airline_selection.iloc[:,2:]],axis=1) print('构建的LRFMC属性前5行为:\n',airline_features.head()) # 数据标准化 from sklearn.preprocessing import StandardScaler data = StandardScaler().fit_transform(airline_features) np.savez('../tmp/airline_scale.npz',data) print('标准化后LRFMC 5个属性为:\n',data[:5,:]) |
标准差标准化处理后,形成ZL、ZR、ZF、ZM、ZC 5个属性的数据集,如表7所示。
表7 标准化处理后的数据集

2.2.4 模型构建
客户价值分析模型构建主要由两个部分构成:第一部分,根据航空公司客户5个指标的数据,对客户作聚类分群。第二部分,结合业务对每个客户群进行特征分析,分析其客户价值,并对每个客户群进行排名。
2.2.4.1客户聚类
采用K-Means聚类算法对客户数据进行客户分群,聚成5类(需要结合业务的理解与分析来确定客户的类别数量)。
使用scikit-learn库下的聚类子库(sklearn.cluster)可以实现K-Means聚类算法。使用标准化后的数据进行聚类,如代码清单7-9所示。
代码清单7-9 K-Meas聚类标准化后的数据
import pandas as pd import numpy as np from sklearn.cluster import KMeans # 导入K-Mmeans算法 # 读取标准化后的数据 airline_scale = np.load('../tmp/airline_scale.npz')['arr_0'] k = 5 # 确定聚类中心数 # 构建模型,随机种子设为123 kmeans_model = KMeans(n_clusters=k, n_jobs=4, random_state=123) fit_kmeans = kmeans_model.fit(airline_scale) # 模型训练 # 查看聚类结果 kmeans_cc = kmeans_model.cluster_centers_ # 聚类中心 print('各类聚类中心为:\n',kmeans_cc) kmeans_labels = kmeans_model.labels_ # 样本的类别标签 print('各样本的类别标签为:\n',kmeans_labels) r1 = pd.Series(kmeans_model.labels_).value_counts() # 统计不同类别样本的数目 print('最终每个类别的数目为:\n',r1) # 输出聚类分群的结果 cluster_center = pd.DataFrame(kmeans_model.cluster_centers_,\ columns = ['ZL','ZR','ZF','ZM','ZC']) # 将聚类中心放在数据框中 cluster_center.index = pd.DataFrame(kmeans_model.labels_ ).\ drop_duplicates().iloc[:,0] # 将样本类别作为数据框索引 print(cluster_center) |
对数据进行聚类分群的结果如表8所示。
表8 客户聚类分群的结果

*由于K-Means聚类是随机选择类标号,因此重复此实验得到的结果中的类标号可能与此不同;另外由于算法的精度问题,重复实验得到的聚类中心也可能略有不同。
2.2.4.2 客户价值分析
针对聚类结果进行特征分析,绘制客户分群雷达图,如代码清单7-10所示。
代码清单7-10 绘制客户分群雷达图
%matplotlib inline #(Jupter中用) import matplotlib.pyplot as plt # 客户分群雷达图 center.index] # 客户群命名 lstype = ['-','--',(0, (3, 5, 1, 5, 1, 5)),':','-.'] kinds = list(cluster_center.iloc[:, 0]) # 由于雷达图要保证数据闭合,因此再添加L列,并转换为 np.ndarray cluster_center = pd.concat([cluster_center, cluster_center[['ZL']]], axis=1) centers = np.array(cluster_center.iloc[:, 0:]) # 分割圆周长,并让其闭合 n = len(labels) angle = np.linspace(0, 2 * np.pi, n, endpoint=False) angle = np.concatenate((angle, [angle[0]])) labels=np.concatenate((labels,[labels[0]])) #对labels进行封闭 # 绘图 fig = plt.figure(figsize=(8,6)) ax = fig.add_subplot(111, polar=True) # 以极坐标的形式绘制图形 plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签 plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号 # 画线 for i in range(len(kinds)): ax.plot(angle, centers[i], linestyle=lstype[i], linewidth=2, label=kinds[i]) # 添加属性标签 ax.set_thetagrids(angle * 180 / np.pi, labels) plt.title('客户特征分析雷达图') plt.legend(legen) plt.show() plt.close |
通过代码清单7-10得到客户分群雷达图,如图12所示。

图12 客户分群雷达图
结合业务分析,通过比较各个特征在群间的大小来对某一个群的特征进行评价分析。其中,客户群1在特征C处的值最大,在特征F、M处的值较小,说明客户群1是偏好乘坐高级舱位的客户群;客户群2在特征F和M上的值最大,且在特征R上的值最小,说明客户群2的会员频繁乘机且近期都有乘机记录;客户群3在特征R处的值大,在特征L、F、M和C处的值都较小,说明客户群3已经很久没有乘机,是入会时间较短的低价值的客户群;客户群4在所有特征上的值都很小,且在特征L处的值最小,说明客户群4属于新入会员较多的客户群;客户群5在特征L处的值最大,在特征R处的值较小,其他特征值都比较适中,说明客户群5入会时间较长,飞行频率也较高,是有较高价值的客户群。
总结出每个客户群的优势和弱势特征,具体结果如表9所示。
表9 客户群特征描述表

注:正常字体表示最大值,加粗字体表示次大值,斜体字体表示最小值,带下划线的字体表示次小值。
根据以上特征分析图表,说明不同用户类别的表现特征明显不同。基于该特征描述,本案例定义5个等级的客户类别:重要保持客户、重要发展客户、重要挽留客户、一般客户与低价值客户。客户类别的特征分析如图13所示。

图13 客户类别的特征分析
(1)重要保持客户
这类客户的平均折扣系数(C)较高(一般所乘航班的舱位等级较高),最近乘机距今的时间长度(R)低,飞行次数(F)司的高价值客户,是最为理想的客户类型,对航空公司的贡献最大,所占比例却较小。航空公司应该优先将资源投放到他们身上,对他们进行差异化管理和一对一营销,提高这类客户的忠诚度与满意度,尽可能延长这类客户的高水平消费。
(2)重要发展客户
这类客户的平均折扣系数(C)较高,最近乘机距今的时间长度(R)低,且飞行次数(F)或总飞行里程(M)较低。这类客户入会时间(L)短,他们是航空公司的潜在价值客户。虽然这类客户的当前价值并不是很高,但却有很大的发展潜力。航空公司要努力促使这类客户增加在本公司的乘机消费和合作伙伴处的消费,也就是增加客户的钱包份额。通过客户价值的提升,加强这类客户的满意度,提高他们转向竞争对手的转移成本,使他们逐渐成为公司的忠诚客户。
(3)重要挽留客户
这类客户过去所乘航班的平均折扣系数(C)、飞行次数(F)或者总飞行里程(M)较高,但是最近乘机距今的时间长度(R)高或者说乘坐频率变小,客户价值变化的不确定性很高。由于这些客户价值衰退的原因各不相同,所以掌握客户的最新信息、维持与客户的互动就显得尤为重要。航空公司应该根据这些客户的最近消费时间以及消费次数的变化情况推测客户消费的异动状况,并列出客户名单,对其重点联系,采取一定的营销手段,延长客户的生命周期。
(4)一般客户与低价值客户
这类客户所乘航班的平均折扣系数(C)很低,最近乘机距今的时间长度(R)高,飞行次数(F)或总飞行里程(M)较低,入会时间(L)短。他们是航空公司的一般客户与低价值客户,可能是在航空公司机票打折促销时,才会乘坐本公司航班。重要挽留客户这3类重要客户分别可以归入客户生命周期管理的发展期、稳定期、衰退期3个阶段。
根据每种客户类型的特征,对各类客户群进行客户价值排名,其结果如表10所示。针对不同类型的客户群提供不同的产品和服务,提升重要发展客户的价值,稳定和延长重要保持客户的高水平消费,防范重要挽留客户的流失并积极进行关系恢复。
表10 客户群价值排名

本模型采用历史数据进行建模,随着时间的变化,分析数据的观测窗口也在变化。因此,对于新增客户的详细信息,考虑业务的实际情况,对于该模型建议每个月运行一次,对新增客户信息通过聚类中心进行判断,同时对本次新增客户的特征进行分析。如增量数据的实际情况与判断结果差异大,需要业务部门重点关注,查看变化大的原因并确认模型的稳定性。如果模型稳定性变化大,需要重新训练模型进行调整。目前模型进行重新训练的时间没有统一标准,大部分情况都是根据经验来决定。根据经验,建议每隔半年训练一次模型比较合适。
2.2.5 模型应用
根据对各个客户群进行特征分析,可以采取下面的一些营销手段和策略,为航空公司的价值客户群管理提供参考。
(1)会员的升级与保级
航空公司的会员可以分为白金卡会员、金卡会员、银卡会员、普通卡会员等,其中非普通卡会员可以统称为航空公司的精英会员。虽然各个航空公司都有自己的特点和规定,但会员制的管理方法大同小异。成为精英会员一般都要求在一定时间内(如一年)积累一定的飞行里程或航段,达到这种要求后就会在有效期内(通常为两年)成为精英会员,并享受相应的高级别服务。有效期快结束时,根据相关评价方法确定客户是否有资格继续作为精英会员,然后对该客户进行相应的升级或降级。然而,由于许多客户并没有意识到或根本不了解会员升级或保级的时间与要求(相关的文件说明往往复杂且不易理解),经常在评价期过后才发现自己其实只差一点就可以实现升级或保级,却错过了机会,使之前的里程积累白白损失。同时,这种认知还可能导致客户的不满,甚至放弃在本公司的消费。
因此,航空公司可以在对会员升级或保级进行评价的时间点之前,对那些接近但尚未达到要求的高价值客户进行适当提醒甚至采取一些促销活动,刺激他们通过消费达到相应标准。这样既可以使航空公司获得收益,又提高了客户的满意度,增加了航空公司的精英会员。
(2)首次兑换
航空公司常旅客计划中最吸引客户的内容就是客户可以通过消费积累的里程来兑换免票或免费升舱等。每个航空公司都有一个首次兑换标准,当客户的里程或航段积累到一定程度时才可以实现第一次兑换,这个标准会高于正常的里程兑换标准。但是很多航空公司的里程积累随着时间的推移进行一定的削减,例如,有的航空公司会在年末对该年积累的里程进行折半处理。这样会导致许多不了解情况的会员白白损失自己好不容易积累的里程,甚至总是难以实现首次兑换。同时,这也会引起客户的不满或流失。对此可以采取的措施是:从数据库中提取出接近但尚未达到首次兑换标准的会员信息,对他们进行适当提醒或采取一些促销活动,使他们通过消费达到兑换标准。一旦实现了首次兑换,客户在本公司进行再次消费兑换就比在其他公司进行首次兑换要容易许多,等于在一定程度上提高了转移的成本。另外,在一些特殊的时间点(如里程折半的时间点)之前可以给客户一些提醒,这样可以增加客户的满意度。
(3)交叉销售
通过发行“联名卡”等与非航空类企业的合作,使客户在其他企业的消费过程中获得本公司的积分,增强与公司的联系,提高他们的忠诚度。例如,可以查看重要客户在非航空类合作伙伴处的里程积累情况,找出他们习惯的里程积累方式(是否经常在合作伙伴处消费、更喜欢消费哪些类型的合作伙伴的产品),为他们制定相应的促销策略。
在客户识别期和发展期可以为客户关系打下基石,但是这两个时期带来的客户关系是短暂的、不稳定的。企业要获取长期的利润,必须具有稳定的、高质量的客户。留住客户对于企业来说是至关重要的,不仅是因为争取一个新客户的成本远远高于维持老客户的成本,更重要的是客户流失会造成公司收益的直接损失。因此,在这一时期,航空公司应该努力维系客户关系水平,使之处于较高的水准,使生命周期内公司与客户的互动价值最大化,并使这样的高水平尽可能保持下去。对于这一阶段的客户,主要应该通过提供优质的服务产品和提高服务水平来提高客户的满意度。通过对常旅客数据库的数据分析,进行客户细分,可以获得重要保持客户的名单。航空公司应该优先将资源投放到他们身上,对他们进行差异化管理和一对一营销,提高这类客户的忠诚度与满意度,尽可能延长这类客户的高水平消费。
所需代码
思考
1)Scikit-learn中K-Means函数中的初始聚类中心可以使用什么算法得到?默认的算法是什么?
2)使用不同的预处理对原始数据进行变换,再使用K-Means算法进行聚类,对比聚类结果,分析不同数据预处理对K-Means算法的影响。

