【作者主页】Francek Chen
【专栏介绍】 ⌈ ⌈ ⌈机器学习与数据挖掘实战 ⌋ ⌋ ⌋ 机器学习是人工智能的一个分支,专注于让计算机系统通过数据学习和改进。它利用统计和计算方法,使模型能够从数据中自动提取特征并做出预测或决策。数据挖掘则是从大型数据集中发现模式、关联和异常的过程,旨在提取有价值的信息和知识。机器学习为数据挖掘提供了强大的分析工具,而数据挖掘则是机器学习应用的重要领域,两者相辅相成,共同推动数据科学的发展。本专栏介绍机器学习与数据挖掘的相关实战案例。
【GitCode】专栏资源保存在我的GitCode仓库:https://gitcode.com/Morse_Chen/ML-DM_cases。
文章目录
- 一、目标分析
- (一)背景
- (二)数据说明
- (三)分析目标
- 二、数据准备
- (一)数据探索
- (二)数据清洗
- 三、特征工程
- (一)特征构造
- (二)特征选择
- (三)特征变换
- 四、模型训练
- 五、性能度量
- (一)结果分析
- (二)客户价值分析
- 小结
一、目标分析
(一)背景
目前,全球经济环境和市场环境正在悄然发生改变,企业的业务也在逐步由产品为主导向客户需求为主导转型。一种全新的“以客户为中心”的业务模式正在形成并被提升到前所未有的高度。随着中国社会经济的发展,我国民航已经从卖方市场转变为买方市场,再加上铁路提速和全国公路网日益完善,不同运输方式间的竞争日趋激烈,航空公司面临的压力越来越大。
航空公司属于典型的服务行业,其目的是获取更多的利润,然而当今航空公司产品同质化现象严重,并且竞争激烈,客户资源成为航空公司最为短缺的资源,谁拥有的客户资源多,谁的核心竞争力就强,获得的利润就会更多。
客户营销战略的倡导者Jay Curry& Adam Curry从国外数百家公司进行了客户营销实施的经验中提炼了如下经验。
- 公司收入的80%来自顶端的20%的客户。
- 20%的客户带来的利润率能够达到100%。
- 90%以上的收入来自现有客户。
- 大部分的营销预算经常被用在非现有客户上。
- 5%至30%的客户在客户金字塔中具有升级潜力。
- 客户金字塔中客户升级2%,意味着销售收入增加10%,利润增加50%。
虽然这些经验也许并不完全准确,但是客户作为航空公司的主要利润来源,要求航空公司不断地认识、发现、开发和满足客户的需求,与客户建立一种稳定的客户关系。这一现实情况揭示了新时代客户分化的趋势,而这种趋势说明了进行客户价值分析的必要性。目前各航空公司都已认识到这一关键因素,并且将客户价值分析作为公司发展战略之一。
本案例将在航空公司客户数据的基础上,建立合理的客户价值模型,对客户进行分群,分析比较不同客户群的客户价值,为企业提供更精准的策略依据,帮助企业制定更加符合市场行情和企业现状的营销策略,为企业带来更多的利润。
(二)数据说明
目前该航空公司已积累了大量的会员档案信息和其乘坐航班记录,以2014年3月31日为结束时间抽取两年内有乘机记录的所有客户的详细数据。数据包含会员卡号、入会时间、性别、年龄、会员卡级别、工作地城市、工作地所在省份、工作地所在国家、观测窗口结束时间、观测窗口乘机积分、飞行公里数、飞行次数、飞行时间、乘机时间间隔、平均折扣率等特征。
本案例所用数据集air_data.csv
内容如下。
本案例所用数据特征名称及说明如下表所示。
特征名称 | 特征说明 | |
---|---|---|
客户基本信息 | MEMBER_NO | 会员卡号 |
FFP_DATE | 入会时间 | |
FIRST_FLIGHT_DATE | 第一次飞行日期 | |
GENDER | 性别 | |
FFP_TIER | 会员卡级别 | |
WORK_CITY | 工作地城市 | |
WORK_PROVINCE | 工作地所在省份 | |
WORK_COUNTRY | 工作地所在国家 | |
AGE | 年龄 | |
乘机信息 | FLIGHT_COUNT | 观测窗口内的飞行次数 |
LOAD_TIME | 观测窗口的结束时间 | |
LAST_TO_END | 最后一次乘机时间至观测窗口结束时长 | |
avg_discount | 平均折扣率 | |
SUM_YR | 观测窗口的票价收入 | |
SEG_KM_SUM | 观测窗口的总飞行公里数 | |
LAST_FLIGHT_DATE | 末次飞行日期 | |
AVG_INTERVAL | 平均乘机时间间隔 | |
MAX_INTERVAL | 最大乘机间隔 | |
积分信息 | EXCHANGE_COUNT | 积分兑换次数 |
EP_SUM | 总精英积分 | |
PROMOPTIVE_SUM | 促销积分 | |
PARTNER_SUM | 合作伙伴积分 | |
POINTS_SUM | 总累计积分 | |
POINT_NOTFLIGHT | 非乘机的积分变动次数 | |
BP_SUM | 总基本积分 |
(三)分析目标
结合目前航空公司的数据情况,可以实现以下目标。
- 借助航空公司客户数据,对客户进行分群。
- 对不同的客户类别进行特征分析,比较不同客户类别客户的客户价值。
- 对不同价值的客户类别提供个性化服务,制定相应的营销策略。
本案例的总体流程主要包括以下4个步骤。
- 抽取航空公司2012年4月1日至2014年3月31日的数据。
- 对抽取的数据进行数据清洗、特征构建和标准化等操作。
- 基于RFM模型,使用K-Means算法进行客户分群。
- 针对模型结果得到不同价值的客户,采用不同的营销手段,提供定制化的服务。
航空公司客户价值分析总体流程如下图所示。
二、数据准备
国内某航空公司提供的原始数据尚未经过处理,数据质量可能尚未达到可以直接用于建模的程度,可能存在缺失值、异常值等问题,这些问题会导致建立的模型不够精确,为尽可能地排除干扰因素、保证模型的可靠性,需要进行必要的数据准备。
(一)数据探索
由于航空公司客户乘机记录信息数据量很大,因此在获取数据时,对原始数据进行截取,以2014年3月31日为结束时间,选取宽度为两年(2012年4月1日~2014年3月31日)的时间段作为分析观测窗口,抽取观测窗口内有乘机记录的所有客户的详细数据形成历史数据,总共62988条记录。
1. 描述性统计分析:查看属性字段的缺失值、最大值、最小值、平均值等情况,从宏观层面上了解数据。
import pandas as pdairline_data = pd.read_csv('../data/air_data.csv')look = airline_data.describe(percentiles=[], include='all').T # 使用统计函数对数据进行统计分析
look['null'] = len(airline_data) - look['count'] # 计算空值数
# describe有很多统计子项,这里就取我们要用到的即可
look = look[['null', 'max', 'min', 'mean']]
look.columns = ['空值记录数', '最大值', '最小值', '平均值']look
截取数据后对数据进行探索,在数据探索过程中,发现数据中存在缺失值和异常值,具体表现为票价为空值、或票价为0、或折扣率为0、或总飞行公里数为0的记录。这些值的存在会对模型的建立产生不可忽视的影响,如模型的不确定性会变得更加显著,其蕴含的规律更难把握,甚至导致模型输出的结果不可靠,因此在数据清洗过程中要重点对这两类数据进行处理。
2. 数据的分布分析:寻找客户信息的分布规律,例如入会时间分布、年龄分布、性别分布、会员等级分布等等。
(1)入会时间分布图展示
import pandas as pd
from datetime import datetime
import matplotlib.pyplot as pltairline_data = pd.read_csv('../data/air_data.csv')ffp = airline_data['FFP_DATE'].apply(lambda x: datetime.strptime(x, '%Y/%m/%d'))
ffp_year = ffp.map(lambda x: x.year)plt.rcParams['font.sans-serif'] = 'SimHei'
plt.rcParams['axes.unicode_minus'] = False
# 绘制各年份会员入会人数直方图
plt.hist(ffp_year, bins='auto')
plt.xlabel('年份')
plt.ylabel('入会人数')
plt.title('各年份会员入会人数')
plt.show()
(2)会员性别比例分布图
import matplotlib.pyplot as pltairline_data = pd.read_csv('../data/air_data.csv')
# 获取会员中不同的性别人数
male = pd.value_counts(airline_data['GENDER'])['男']
female = pd.value_counts(airline_data['GENDER'])['女']# 绘制会员分布饼状图
plt.rcParams['font.sans-serif'] = 'SimHei'
plt.rcParams['axes.unicode_minus'] = False
plt.pie([male, female], labels=['男', '女'], autopct='%1.1f%%')
plt.title('会员性别比例')
plt.show()
(3)会员年龄分布箱型图
import pandas as pd
from datetime import datetime
import matplotlib.pyplot as pltairline_data = pd.read_csv('../data/air_data.csv')
# 提取会员的年龄
age = airline_data['AGE'].dropna()
age = age.astype('int64')# 绘制会员年龄分布箱型图
plt.rcParams['font.sans-serif'] = 'SimHei'
plt.rcParams['axes.unicode_minus'] = False
plt.boxplot(age, patch_artist=True, labels=['会员年龄'])
plt.title('会员年龄分布箱型图')
plt.grid(axis='y')
plt.show()
3. 数据属性之间的相关性分析:这对特征的选择来说非常有用,通过分析属性之间的关联性,可以确定选择哪些属性作为特征值,哪些则是可以忽略的。
# 相关性分析
import pandas as pd
from datetime import datetime# 读取数据
airline_data = pd.read_csv('../data/air_data.csv')
# 创建相关性计算的数据框
data_corr = airline_data[['FFP_TIER', 'FLIGHT_COUNT', 'LAST_TO_END', 'SEG_KM_SUM', 'EXCHANGE_COUNT', 'Points_Sum']].copy()
# 填充AGE的缺失值并转换为整数
age_1 = airline_data['AGE'].fillna(0)
data_corr.loc[:, 'AGE'] = age_1.astype('int64') # 使用 .loc 来修改列# 处理FFP_DATE并提取年份
ffp = airline_data['FFP_DATE'].apply(lambda x: datetime.strptime(x, '%Y/%m/%d'))
ffp_year = ffp.map(lambda x: x.year)
data_corr.loc[:, 'ffp_year'] = ffp_year # 使用 .loc 来修改列
# 计算相关性矩阵
dt_corr = data_corr.corr(method='pearson')
print(dt_corr)
从上面的图可以看出,有些属性的相关性较强,有些则较弱。例如ffp_year
与FFP_TIER
的相关性就弱,已经是负相关了。而FLIGHT
与FFP_TIER
的相关性就稍微强一些。属性之间的相关性关系,也是在做特征降维的一个重要参考量,有时候特征较多会严重增加建模的时间,为了提高效率,需要对特征进行降维,构建有代表性的特征进行建模。
(二)数据清洗
在数据清洗过程中,因为原始数据量大,缺失值和异常值在数据集中占比较小,所以需要对缺失值和异常值均进行删除处理,即丢弃票价为0,或平均折扣率为0,或总飞行公里数为0的记录。
相关代码如下。
# 数据清洗
import pandas as pdairline_data = pd.read_csv('../data/air_data.csv')
print('原始数据的形状为:', airline_data.shape)
# 去除票价为空的记录
index_not_na1 = airline_data['SUM_YR_1'].notnull()
index_not_na2 = airline_data['SUM_YR_2'].notnull()
index_not_na = index_not_na1 & index_not_na2
airline_notnull = airline_data.loc[index_not_na, :]
print('删除缺失记录后数据的形状为:', airline_notnull.shape)# 丢弃票价为0,或平均折扣率为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)
index_drop = airline_notnull.index[(index1 & index2) | index3]
airline = airline_notnull.drop(index_drop, axis=0)
airline.to_csv('../tmp/air_data_clean.csv')
print('删除异常记录后数据的形状为:', airline.shape)
三、特征工程
在建模之前需要对原始数据特征进行处理,筛选出更好的特征,才能获取更好的训练数据,让建立的模型能够得到更加精确的结果。特征构造是指从原始数据中人工的构建一些具有实际意义的特征,本案例借助RFM模型进行特征构造。
(一)特征构造
1. RFM模型
RFM模型是识别客户价值应用较为广泛的模型,RFM模型具体的含义如下。
(1)R(Recency)
R(Recency)指的是最近一次消费时间与截止时间的间隔,简称时间间隔。通常情况下,最近一次消费时间与截止时间的间隔越短,对即时提供的商品或是服务也最有可能感兴趣。这也是消费时间间隔0至6个月的顾客收到的沟通信息多于1年以上的顾客的原因。
最近一次消费时间与截止时间的间隔不仅能够为确定促销客户群体提供依据,还能够从中得出企业发展的趋势。如果分析报告显示最近一次消费时间很近的客户在增加,则表示该公司是个稳步上升的公司。反之,最近一次消费时间很近的客户越来越少,则说明该公司需要找到问题所在,及时调整营销策略。
(2)F(Frequency)
F(Frequency)指顾客在某段时间内所消费的次数,简称消费频率。可以说消费频率越高的顾客,也是满意度越高的顾客,其忠诚度也就越高,顾客价值也就越大。增加顾客购买的次数意味着从竞争对手处争取市场占有率,赚取营业额。商家需要做的是通过各种营销方式,去不断地刺激顾客消费,提高他们的消费频率,提升顾客的复购率。
(3)M(Monetary)
M(Monetary)指顾客在某段时间内所消费的金额,简称消费金额。消费金额越大的顾客,他们的消费能力自然也就越大,这就是所谓“20%的顾客贡献了80%的销售额”的二八法则。而这批顾客也必然是商家在进行营销活动时需要特别照顾的群体,尤其是在商家前期资源不足的时候。不过需要注意一点,不论采用哪种营销方式,以不对顾客造成骚扰为大前提,否则营销只会产生负面效果。
在RFM模型理论中,时间间隔、消费频率、消费金额是判别客户价值最重要的特征,这3个特征对营销活动的具有十分重要的意义,其中,时间间隔是最有力的特征。
2. RFM模型解读
RFM模型包括3个特征,无法用平面坐标图来展示,所以这里使用三维坐标系进行展示,X轴表示Recency,Y轴表示Frequency,Z轴表示Monetary,每个轴一般会分成5级表示程度,1为最小,5为最大。需要特别说明的是,R特征,在X轴上R值越大代表该类客户最近一次消费与截止时间的消费间隔越短,客户R维度上的质量越好。X轴表示R特征,Y轴表示F特征,Z轴表示M指标,每个轴上划分5等级,等价于将客户划分为5×5×5=125。这里划分为5级并不是严格的要求,一般是根据实际研究需求和顾客的总量进行划分,对于是否等分的问题取决于该维度上客户的分布规律。
通过下图可以看出,左上角方框的客户RFM特征取值为155。消费的近度R值是比较小的,说明该类客户最近都没有来店消费,原因可能是因为最近比较忙或对现有的产品或服务不满意,或是找到了更好的商家。R特征数值变小需要企业管理人员引起重视,说明该类客户可能流失,对企业造成损失。消费频率F很高,说明客户很活跃,经常到商家消费。消费金额M值很高,说明该类客户是具备一定的消费能力,为店里贡献了很多的营业额。这类型客户总体分析比较优质,但是R特征时间近度值较小,其往往是需要针对进行营销优化的客户群体。
同理,若客户RFM特征取值为555。则可以判定该客户为最优质客户,即该类客户最近有到商家消费,消费频率很高,消费金额很大,该类客户往往是企业利益的主要贡献者,是需要重点关注与维护的客户。
3. 特征构造
在RFM模型中,消费金额表示客户在一段时间内购买该企业产品金额的总和。然而航空票价受到多种因素(如距离、舱位等级)的影响,因此消费同样金额的不同客户对航空公司的价值可能是不同的,如一位购买长航线,低等级舱位票的旅客与一位购买短航线,高等级舱位票的旅客相比,后者对于航空公司而言价值可能更高。因此RFM模型中的消费金额这一特征并不适用于航空公司客户价值分析。
本案例在RFM模型的基础上,选择客户在一定时间内累积的飞行里程M、客户在一定时间内乘坐舱位所对应的折扣系数的平均值C。同时,因为航空公司会员入会时间的长短在一定程度上能够影响客户价值,所以在模型中增加客户关系长度L,作为区分客户的另一特征。
(二)特征选择
本案例选择客户关系长度L、时间间隔R、消费频率F、飞行里程M和折扣系数的平均值C作为航空公司识别客户价值的特征,记为LRFMC模型。
L | R | F | M | C |
---|---|---|---|---|
会员入会时间距观测窗口结束的月数 | 客户最近一次乘坐公司飞机距观测窗口结束的月数 | 客户在观测窗口内乘坐公司飞机的次数 | 客户在观测窗口内累计的飞行里程 | 客户在观测窗口内乘坐舱位所对应的折扣系数的平均值 |
根据航空公司客户价值LRFMC模型,选择与LRFMC特征相关的6个特征:FFP_DATE、LOAD_TIME、FLIGHT_COUNT、avg_discount、SEG_KM_SUM、LAST_TO_END。
LOAD_TIME | FFP_DATE | LAST_TO_END | FLIGHT_COUNT | SEG_K_M_SUM | AVG_DISCOUNT |
---|---|---|---|---|---|
2014/3/31 | 2013/3/16 | 23 | 14 | 126850 | 1.02 |
2014/3/31 | 2012/6/26 | 6 | 65 | 184730 | 0.76 |
2014/3/31 | 2009/12/8 | 2 | 33 | 60387 | 1.27 |
2014/3/31 | 2009/12/10 | 123 | 6 | 62259 | 1.02 |
2014/3/31 | 2011/8/25 | 14 | 22 | 54730 | 1.36 |
2014/3/31 | 2012/9/26 | 23 | 26 | 50024 | 1.29 |
2014/3/31 | 2010/12/27 | 77 | 5 | 61160 | 0.94 |
2014/3/31 | 2009/10/21 | 67 | 4 | 48928 | 1.05 |
2014/3/31 | 2010/4/15 | 11 | 25 | 43499 | 1.33 |
2014/3/31 | 2007/1/26 | 22 | 36 | 68760 | 0.88 |
相关代码如下。
import pandas as pd
import numpy as npairline = pd.read_csv('../data/air_data.csv')
# 选取需求特征
airline_selection = airline[['FFP_DATE', 'LOAD_TIME', 'FLIGHT_COUNT', 'LAST_TO_END', 'avg_discount', 'SEG_KM_SUM']]
# 构建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_features1 = pd.concat([L, airline_selection.iloc[:, 2:]], axis = 1)
airline_features1.columns = ['L', 'F', 'R', 'C', 'M']
airline_features = pd.DataFrame(np.zeros([len(airline_features1), 5]), columns = ['L', 'R', 'F', 'M', 'C'])
for i in range(len(airline_features.columns)):airline_features.loc[:, airline_features.columns[i]] = list(airline_features1.loc[:, airline_features.columns[i]])print('构建的L、R、F、M、C特征前5行为:\n', airline_features.head())
(三)特征变换
由于选取的L、R、F、M、C特征在原始数据中并没有直接给出,因此需要根据原始数据特征进行特征变换得到需要的特征。
- L = 观测窗口的结束时间 - 入会时间 = LOAD_TIME-FFP_DATE
- R = 最后一次乘机时间至观察窗口末端时长 = LAST_TO_END
- F = 观测窗口的飞行次数 = FLIGHT_COUNT
- M = 观测窗口总飞行公里数 = SEG_KM_SUM
- C = 平均折扣率 = avg_discount
相关代码如下。
# 查看特征取值范围
explore = airline_features.describe(percentiles = [], include = 'all')
explore = explore.loc[['min', 'max'], :]
print('L、R、F、M、C 5个特征取值范围:\n', explore )
# 数据标准化
from sklearn.preprocessing import StandardScaler
air_scale = StandardScaler().fit_transform(airline_features)
np.savez('../tmp/airline_scale.npz', air_scale)
print('标准化后L、R、F、M、C 5个特征为:\n', air_scale[:5, :])
四、模型训练
采用K-Means聚类算法对航空公司客户进行分群,K-Means聚类需要预先给出k值,即需要事先指定聚类数目,本案例根据对业务的理解与分析结合Calinski-Harabasz指数确定聚类数目k,Calinski-Harabasz指数越大表示聚类效果越好,在建模过程中k取Calinski-Harabasz指数最大值对应的聚类数。
相关代码如下。
from sklearn.cluster import KMeans # 导入KMeans算法
import matplotlib.pyplot as plt # 导入画图库
from sklearn import metrics # 导入计算Calinski-Harabasz指数的库
import pandas as pd
import numpy as npairline_scale = np.load('../tmp/airline_scale.npz')['arr_0']
# 利用Calinski-Harabasz指数确定聚类数目
CH = []
for i in range(3, 6):model = KMeans(n_clusters = i, n_jobs=4, random_state =123).fit(airline_scale)labels = model.labels_CH.append(metrics.calinski_harabasz_score(airline_scale, labels))
k = CH.index(max(CH)) + 3 # 确定聚类中心数
print('最佳聚类数目', k)# 绘制不同聚类数目与对应的Calinski-Harabasz指数折线图
x = range(3, 6) # x为折线图中的横坐标
plt.plot(x, CH, '-xr')
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
plt.title('不同聚类数目对应的Calinski-Harabasz指数')
plt.show()# 构建模型
kmeans_model = KMeans(n_clusters = k, n_jobs=4, random_state=123)
fit_kmeans = kmeans_model.fit(airline_scale) # 模型训练
# 查看聚类中心
print('聚类中心为:\n', kmeans_model.cluster_centers_)
print('保留小数点后4位后聚类中心为:\n', np.round(kmeans_model.cluster_centers_, 4))print('样本类别标签为', kmeans_model.labels_) # 查看样本的类别标签# 统计不同类别样本的数目
count_class = pd.Series(kmeans_model.labels_).value_counts()
print('最终每个类别的数目为:\n', count_class)cluster_centers = pd.DataFrame(kmeans_model.cluster_centers_)
cluster_centers.to_csv('../tmp/cluster_centers.csv', index=False) # 保存聚类中心labels = pd.DataFrame(kmeans_model.labels_)
labels.to_csv('../tmp/labels.csv', index=False) # 保存聚类类别标签
五、性能度量
本案例中K-Means模型采用历史数据进行建模,随着时间的变化,分析数据的观测窗口在变化,航空公司客户的数据信息也在变化。因此,考虑业务的实际情况,建议每个月运行一次该模型,通过聚类判断新增加的客户所属的客户群,同时分析新增客户特征的价值。如果新增加客户数据的实际情况与判断结果差异较大,那么需要业务部门重点关注,查看出现差异的原因并确认模型的稳定性,如果模型稳定性变化较大,那么需要重新训练聚类模型。
(一)结果分析
客户分群聚类结果如表所示。
聚类类别 | 聚类个数 | 聚类中心 | ||||
---|---|---|---|---|---|---|
ZL | ZR | ZF | ZM | ZC | ||
客户群1 | 5563 | 0.4793 | -0.796 | 2.4384 | 2.3832 | 0.3819 |
客户群2 | 12939 | -0.3092 | 1.659 | -0.5721 | -0.5359 | -0.0183 |
客户群3 | 17253 | 1.1388 | -0.3667 | -0.0957 | -0.1049 | 0.0957 |
客户群4 | 26288 | -0.6961 | -0.4085 | -0.1696 | -0.1698 | -0.1343 |
根据聚类结果绘制雷达图,如图所示。相关代码如下。
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np# 客户分群雷达图
cluster_center = pd.read_csv('../tmp/cluster_centers.csv')
labels = pd.read_csv('../tmp/labels.csv')
cluster_center.columns = ['ZL', 'ZR', 'ZF', 'ZM', 'ZC'] # 将聚类中心放在数据框中
cluster_center.index = labels.drop_duplicates().iloc[:, 0] # 将样本类别作为数据框索引
label = ['ZL', 'ZR', 'ZF', 'ZM', 'ZC']
lstype = ['-','--',':','-.']
legen = ['客户群' + str(i + 1) for i in cluster_center.index] # 客户群命名,作为雷达图的图例
kinds = list(cluster_center.iloc[:, 0])# 由于雷达图要保证数据闭合,因此再添加ZL列 ,并转换为 np.ndarray
cluster_center = pd.concat([cluster_center, cluster_center[['ZL']]], axis=1)
centers = np.array(cluster_center.iloc[:, 0:])
# 分割圆周长,并让其闭合
n = len(label)
angle = np.linspace(0, 2 * np.pi, n, endpoint = False)
angle = np.concatenate((angle, [angle[0]]))# 绘图
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, label)
plt.title('客户特征分析雷达图')
plt.legend(legen)
plt.savefig('客户特征分析雷达图.jpg', dpi=2080) #指定分辨率保存
plt.show()
客户群1在特征F、M处的值最大,在特征R处的值最小,说明客户群1消费频率和累积飞行里程较大,消费时间间隔较小,这类客户需要航空公司重点关注并保持良好关系,称F、M、R特征为客户群1的优势特征。
客户群2在L、C特征处的值最小,说明客户群2入会时间较短、享受的平均折扣系数较小。
客户群3在R特征处的值最大,在F、M特征处的值最小,说明客户群3消费频率和累积飞行里程较小,消费时间间隔较大,这类客户可能只有在机票打折的时候才会乘坐航空公司航班,称F、M、R特征为客户群3的弱势特征。
客户群4在特征L处的值最大,说明客户群4入会时间较长。
每个客户群的优势特征和弱势特征总结如表所示,其中正常字体表示最大值,加粗字体表示次大值,斜体字体表示最小值。
群类别 | 优势特征 | 弱势特征 | ||||
---|---|---|---|---|---|---|
客户群1 | F | M | R | |||
客户群2 | L | C | ||||
客户群3 | F | M | R | |||
客户群4 | L | F | M |
(二)客户价值分析
-
重要保持客户:平均折扣系数C较高,时间间隔R较低,消费频率(乘机次数)F或累积飞行里程M较高。这类客户是航空公司最理想的客户,他们为航空公司带来了大部分的利润,但是这类客户占的比例比较小,航空公司应该优先考虑将营销资源投入到这类客户,尽量使这类客户能够保持在公司的高质量消费。
-
重要挽留客户:在过去的时间里平均折扣系数C,消费频率(乘机次数)F或飞行里程M较高,但是时间间隔R较大或消费频率(乘机次数)F逐渐变小。这类客户存在较高的不确定性因素,航空公司应该提高警惕,采取一定的营销手段,延长客户在航空公司的消费周期,否则,这些不确定因素可能导致这类客户的流失。
-
一般与低价值客户:平均折扣系数C较低,时间间隔R较高,消费频率(乘机次数)F或飞行里程M较低,会员入会时间L较低。对于这类客户,航空公司不需要过多地关注,因为他们可能只有在机票打折的时候才会乘坐航空公司航班。
根据客户类别特征描述,对模型得出的客户群进行客户价值排名,如表所示。针对不同类别的客户群航空公司应该采取不同的营销策略,对不同类型的客户群提供不同的产品和服务,稳定和延长重要保持客户的高水平消费,防范重要挽留客户的流失。
客户群 | 排名 | 排名含义 |
---|---|---|
客户群1 | 1 | 重要保持客户 |
客户群2 | 3 | 一般客户 |
客户群3 | 2 | 重要挽留用户 |
客户群4 | 4 | 低价值客户 |
小结
本案例结合航空公司客户的会员乘机记录信息,重点介绍了K-Means聚类算法在客户价值分析中的应用。
首先对原始数据进行探索,寻找数据特点,对原始数据进行清洗,处理缺失值和异常值。然后对RFM模型进行改进,构造LRFMC模型,进而构建特征集合。最后根据对业务的理解和分析结合Calinski-Harabasz指数确定最佳聚类数目,利用K-Means聚类算法对航空公司客户分群,对聚类得出的客户群进行特征分析,划分客户类别,并给出一定的策略建议。
附:以上文中的数据集及相关资源下载地址:
链接:https://pan.quark.cn/s/3fdf442547c7
提取码:13nH