本案例的目标是客户价值识别。
识别客户价值应用最广泛的模型是通过3个指标(最近消费时间间隔(Recency)、消费频率(Frequency)和消费金额(Monetary))来进行客户细分,识别出高价值的客户,简称RFM模型。
在RFM模型中,消费金额表示在一段时间内,客户购买该企业产品金额的总和。由于航空票价受到运输距离、舱位等级等多种因素影响,同样消费金额的不同旅客对航空公司的价值是不同的。例如,一位购买长航线、低等级舱位票的旅客与一位购买短航线、高等级舱位票的旅客相比,后者对于航空公司而言价值可能更高。因此,这个指标并不适用于航空公司的客户价值分析。
我们选择客户在一定时间内累积的飞行里程M和客户在一定时间内乘坐舱位所对应的折扣系数的平均值C两个指标代替消费金额。此外,考虑航空公司会员入会时间的长短在一定程度上能够影响客户价值,所以在模型中增加客户关系长度L,作为区分客户的另一指标。
本案例将客户关系长度L、消费时间间隔R、消费频率F、飞行里程M和折扣系数的平均值C五个指标作为航空公司识别客户价值指标(见表7-3 ),记为LRFMC模型。
针对航空公司LRFMC模型,如果采用传统RFM模型分析的属性分箱方法(依据属性的平均值进行划分,其中大于平均值的表示为↑,小于平均值的表示为↓),虽然也能够识别出最有价值的客户,但是细分的客户群太多,提高了针对性营销的成本。因此,本案例采用聚类的方法识别客户价值。通过对航空公司客户价值的LRFMC模型的五个指标进行K-Means聚类,识别出最有价值客户。
本案例航空客户价值分析的总体流程
航空客运信息挖掘主要包括以下步骤。
import numpy as np
import pandas as pd
from sklearn.cluster import KMeans
data = pd.read_csv('./chapter7/demo/data/air_data.csv')
data.info()
explore = data.describe(percentiles= [], include= 'all').T # percentiles,统计中的百分位数
explore['null'] = len(data) - explore['count'] # 添加空值数量列
explore = explore[['null', 'max', 'min']]
explore
通过数据探索分析,发现数据中存在缺失值,票价最小值为0、折扣率最小值为0的记录。由于原始数据量大,这类数据所占比例较小,对于问题影响不大,因此对其进行丢弃处理。具体处理方法如下。
# 数据清洗
data = data[data['SUM_YR_1'].notnull() & data['SUM_YR_2'].notnull()]
index1 = (data['SUM_YR_1'] != 0) & (data['SEG_KM_SUM'] != 0) # 票价不为0且有总公里数,避免票价不为0却没有总公里数的错误数据
index2 = (data['SUM_YR_2'] != 0) & (data['SEG_KM_SUM'] != 0)
index3 = (data['SEG_KM_SUM'] != 0) & (data['avg_discount'] == 0) # 总飞行公里数不为0时平均折扣率为0,可能是0折机票或积分兑换(积分兑换算在平均折扣里吗)
data = data[index1 | index2 | index3] # 当三个判断都为false时丢弃该数据,index1,2票价为0时,index3:总公里数不为0,有折扣却不为0,票价异常,或总公里数等于0
data
原始数据中属性太多,根据航空公司客户价值LRFMC模型,选择与LRFMC 指标相关的6个属性:FFP_DATE、LOAD_TIME、FLIGHT_COUNT、AVG_DISCOUNT、SEG_KM_SUM、LAST_TO_END。删除与其不相关、弱相关或冗余的属性,例如,会员卡号、性别、工作地城市、工作地所在省份、工作地所在国家和年龄等属性。
data = data[['LOAD_TIME', 'FFP_DATE', 'LAST_TO_END', 'FLIGHT_COUNT', 'SEG_KM_SUM', 'avg_discount']]
data
数据变换是将数据转换成“适当的”格式,以适应挖掘任务及算法的需要。本案例中主要采用的数据变换方式为属性构造和数据标准化。
由于原始数据中并没有直接给出LRFMC五个指标,需要通过原始数据提取这五个指标,具体的计算方式如下。
5个指标的数据提取后,对每个指标数据分布情况进行分析,5个指标的取值范围数据差异较大,为了消除数量级数据带来的影响,需要对数据进行标准化处理。
L = (pd.to_datetime(data['LOAD_TIME']) - pd.to_datetime(data['FFP_DATE']))
lrfmc = pd.DataFrame((L / np.timedelta64(1, 'D')) / 30, columns= ['L'])
lrfmc['R'] = data['LAST_TO_END'] / 30
lrfmc['F'] = data['FLIGHT_COUNT']
lrfmc['M'] = data['SEG_KM_SUM']
lrfmc['C'] = data['avg_discount']
lrfmc
lrfmc = (lrfmc - lrfmc.mean()) / lrfmc.std()
lrfmc.columns = ['Z' + i for i in lrfmc.columns]
lrfmc
k = 5
kmodel = KMeans(n_clusters= k)
kmodel.fit(lrfmc)
result = pd.DataFrame({"聚类类别": ['客户群1', '客户群2', '客户群3', '客户群4', '客户群5']})
c1 = pd.Series(kmodel.labels_).value_counts()
r2 = pd.DataFrame(kmodel.cluster_centers_)
r = pd.concat([c1, r2], axis=1)
result = pd.concat([result, r], axis =1)
result.columns = ['聚类类别', '聚类个数', 'ZL', 'ZR', 'ZF', 'ZM', 'ZC']
result
result_lp = result.iloc[:, 2:]
import plotly.graph_objects as go
fig = go.Figure()
categories = ['ZL', 'ZR', 'ZF', 'ZM', 'ZC']
fig.add_trace(go.Scatterpolar(r= result_lp.loc[0], theta= categories, fill= 'toself', name= '客户群1'))
fig.add_trace(go.Scatterpolar(r= result_lp.loc[1], theta= categories, fill= 'toself', name= '客户群2'))
fig.add_trace(go.Scatterpolar(r= result_lp.loc[2], theta= categories, fill= 'toself', name= '客户群3'))
fig.add_trace(go.Scatterpolar(r= result_lp.loc[3], theta= categories, fill= 'toself', name= '客户群4'))
fig.add_trace(go.Scatterpolar(r= result_lp.loc[4], theta= categories, fill= 'toself', name= '客户群5'))
fig.update_layout(polar= dict(radialaxis= dict(visible= True,range = [-1, 2.5])))
fig.show()
其中,重要发展客户、重要保持客户、重要挽留客户这三类重要客户分别可以归人客户生命周期管理的发展期、稳定期、衰退期三个阶段。
根据每种客户类型的特征,对各类客户群进行客户价值排名。针对不同类型的客户群提供不同的产品和服务,提升重要发展客户的价值、稳定和延长重要保持客户的高水平消费、防范重要挽留客户的流失并积极进行关系恢复。