一、背景与挖掘目标
面对激烈的市场竞争,各个航空公司相继推出了更优惠的营销方式来吸引更多的客户,国内某航空公司面临着常旅客流失、竞争力下降和航空资源未充分利用等经营危机。通过建立合理的客户价值评估模型,对客户进行分类,分析比较不同客户群体的价值,并制定相应的营销策略,对不同的客户群提供个性化的客户服务是必须的和有效的。结合该航空公司已累积的大量的会员档案信息和其乘坐航班记录,实现以下目标:
1)借助航空公司客户数据,对客户进行分类。
2)对不同的客户类别进行特征分析,比较不同类别的客户的价值。
3)针对不同价值的客户类别制定相应的营销策略,为其提供个性化服务。
二、分析方法与过程
在客户价值分析领域,最具影响力并得到实证检验的理论与模型有:客户终生价值理论、客户价值金字塔模型、策略评估矩阵分析法和 RFM客户价值分析模型等。
(一)分析步骤与流程
航空公司客户价值分析案例的总体流程如图所示,主要包括以下4个步骤:
1)抽取航空公司2012年4月1日至2014年3月31日的数据。
2)对抽取的数据进行数据探索分析与预处理,包括数据缺失值与 异常值的探索分析、数据清洗、特征构建、标准化等操作。
3)基于RFM模型,使用K-Means算法进行客户分群。
4)针对模型结果得到不同价值的客户,采用不同的营销手段,提供定制化的服务。
(二)数据探索分析
根据航空公司系统内的客户基本信息、乘机信息以及积分信息等详细数据,依据末次飞行日期(LAST_FLIGHT_DATE),以2014年3月31日为结束时间,选取宽度为两年的时间段作为分析观测窗口,抽取观测窗口2012年4月1日至2014年3月31日内有乘机记录的所有客户的详细数据形成历史数据,总共62988条记录。其中包含了会员卡号、入会时 间、性别、年龄、会员卡级别、工作地城市、工作地所在省份、工作地 所在国家、观测窗口结束时间、观测窗口乘机积分、飞行公里数、飞行 次数、飞行时间、乘机时间间隔、平均折扣率等44个属性,如表7-1所 示。
1、描述性统计分析
通过对原始数据观察发现数据中存在票价为空值的记录,同时存在票价最小值为0、折扣率最小值为0但总飞行公里数大于0的记录。票价为空值的数据可能是客户不存在乘机记录造成的。其他的数据可能是客户乘坐0折机票或者积分兑换造成的。
首先查找每列属性观测值中空值个数、最大值、最小值。
1 #7-1 数据探索 2 3 # 对数据进行基本的探索 4 # 返回缺失值个数以及最大、最小值 5 import pandas as pd 6 datafile= 'E:/大三下/数据分析/数据/第七章/air_data.csv' # 航空原始数据,第一行为属性标签 7 resultfile = 'E:/大三下/数据分析/数据/第七章/explore.csv' # 数据探索结果表 8 9 # 读取原始数据,指定UTF-8编码(需要用文本编辑器将数据转换为UTF-8编码) 10 data = pd.read_csv(datafile, encoding = 'utf-8') 11 12 # 包括对数据的基本描述,percentiles参数是指定计算多少的分位数表(如1/4分位数、中位数等) 13 explore = data.describe(percentiles = [], include = 'all').T 14 # describe()函数自动计算非空值数,需要手动计算空值数 15 explore['null'] = len(data)-explore['count'] 16 17 explore = explore[['null', 'max', 'min']] 18 explore.columns = [u'空值数', u'最大值', u'最小值'] #表头重命名 19 ''' 20 这里只选取部分探索结果。 describe()函数自动计算的字段有count(非空值数)、 21 unique(唯一值数)、top(频数最高者)、 freq(最高频数)、mean(平均值)、std(方差)、 22 min(最小值)、50%(中位数)、max(最大值) ''' 23 24 explore.to_csv(resultfile) # 导出结果
根据代码7-1得到的探索结果为下表。
2、分布分析
分别从客户基本信息、乘机信息、积分信息3个角度进行数据探索,寻找客户信息的分布规律。
(1)客户基本信息分布分析
选取客户基本信息的入会时间、性别、会员卡级别和年龄字段进行探索分析,探索客户的基本信息分布情况。
1 #7-2 探索客户的基本信息分布分析 2 3 # 客户信息类别 4 # 提取会员入会年份 5 import pandas as pd 6 import matplotlib.pyplot as plt 7 from datetime import datetime 8 datafile= 'E:/大三下/数据分析/数据/第七章/air_data.csv' 9 data = pd.read_csv(datafile, encoding = 'utf-8') 10 ffp = data['FFP_DATE'].apply(lambda x:datetime.strptime(x,'%Y/%m/%d')) 11 ffp_year = ffp.map(lambda x : x.year) 12 # 绘制各年份会员入会人数直方图 13 fig = plt.figure(figsize=(8 ,5)) #设置画布大小 14 plt.rcParams['font.sans-serif'] = 'SimHei' #设置中文显示 15 plt.rcParams['axes.unicode_minus'] = False 16 plt.hist(ffp_year, bins='auto', color='#0504aa') 17 plt.xlabel('年份') 18 plt.ylabel('入会人数') 19 plt.title('2019114243032 各年份会员入会人数') 20 plt.show() 21 plt.close 22 23 # 提取会员不同性别人数 24 male = pd.value_counts(data['GENDER'])['男'] 25 female = pd.value_counts(data['GENDER'])['女'] 26 # 绘制会员性别比例饼图 27 fig = plt.figure(figsize=(7 ,4)) 28 plt.pie([ male, female], labels=['男','女'], colors=['lightskyblue', 'lightcoral'], 29 autopct='%1.1f%%') 30 plt.title('2019114243032 会员性别比例') 31 plt.show() 32 plt.close 33 34 # 提取不同级别会员的人数 35 lv_four = pd.value_counts(data['FFP_TIER'])[4] 36 lv_five = pd.value_counts(data['FFP_TIER'])[5] 37 lv_six = pd.value_counts(data['FFP_TIER'])[6] 38 # 绘制会员各级别人数条形图 39 fig = plt.figure(figsize=(8 ,5)) 40 plt.bar(x=range(3), height=[lv_four,lv_five,lv_six], width=0.4, alpha=0.8, color='skyblue') 41 plt.xticks([index for index in range(3)], ['4','5','6']) 42 plt.xlabel('会员等级') 43 plt.ylabel('会员人数') 44 plt.title('2019114243032 会员各级别人数') 45 plt.show() 46 plt.close() 47 48 # 提取会员年龄 49 age = data['AGE'].dropna() 50 age = age.astype('int64') 51 # 绘制会员年龄分布箱型图 52 fig = plt.figure(figsize=(5 ,10)) 53 plt.boxplot(age, 54 patch_artist=True, 55 labels = ['会员年龄'], # 设置x轴标题 56 boxprops = {'facecolor':'lightblue'}) # 设置填充颜色 57 plt.title('2019114243032 会员年龄分布箱型图') 58 # 显示y坐标轴的底线 59 plt.grid(axis='y') 60 plt.show() 61 plt.close
由各年份会员入会人数直方图可看出:入会人数随年份的增长而增加,在2012年达到最高峰。
由会员性别比例饼图可看出:男性会员明显比女性会员多。
由会员各级别人数条形图可看出:绝大部分会员为4级会员,仅有少数会员为5级会员或6级会员。
由会员年龄分布箱型图可看出:大部分会员年龄集中在30-50岁之间,极少量的会员年龄小于20岁或高于60岁,且存在一个超过100岁的异常数据。
(2)客户乘机信息分布分析
选取最后一次乘机至结束的时长、客户乘机信息中的飞行次数、总飞行公里数进行探索分析,探索客户的乘机信息分布情况。
1 #7-3 探索客户乘机信息分布情况 2 import pandas as pd 3 import matplotlib.pyplot as plt 4 datafile= 'E:/大三下/数据分析/数据/第七章/air_data.csv' 5 data = pd.read_csv(datafile, encoding = 'utf-8') 6 7 lte = data['LAST_TO_END'] 8 fc = data['FLIGHT_COUNT'] 9 sks = data['SEG_KM_SUM'] 10 11 # 绘制最后乘机至结束时长箱型图 12 fig = plt.figure(figsize=(5 ,8)) 13 plt.boxplot(lte, 14 patch_artist=True, 15 labels = ['时长'], # 设置x轴标题 16 boxprops = {'facecolor':'lightblue'}) # 设置填充颜色 17 plt.title('2019114243032 会员最后乘机至结束时长分布箱型图') 18 # 显示y坐标轴的底线 19 plt.grid(axis='y') 20 plt.show() 21 plt.close 22 23 # 绘制客户飞行次数箱型图 24 fig = plt.figure(figsize=(5 ,8)) 25 plt.boxplot(fc, 26 patch_artist=True, 27 labels = ['飞行次数'], # 设置x轴标题 28 boxprops = {'facecolor':'lightblue'}) # 设置填充颜色 29 plt.title('2019114243032 会员飞行次数分布箱型图') # 显示y坐标轴的底线 30 plt.grid(axis='y') 31 plt.show() 32 plt.close 33 34 # 绘制客户总飞行公里数箱型图 35 fig = plt.figure(figsize=(5 ,10)) 36 plt.boxplot(sks, 37 patch_artist=True, 38 labels = ['总飞行公里数'], # 设置x轴标题 39 boxprops = {'facecolor':'lightblue'}) # 设置填充颜色 40 plt.title('2019114243032 客户总飞行公里数箱型图') 41 # 显示y坐标轴的底线 42 plt.grid(axis='y') 43 plt.show() 44 plt.close
根据会员最后一次乘机至结束的时长箱型图,客户的入会时长主要分布在50~300区间内,另外有一 部分客户群体的入会时长分布在600以上的区间,可分为两个群体。根据客户飞行次数分布箱型图和客户总飞行公里数箱型图,客户的飞行次数与总飞行公里数也明显地分为两个群体,大 部分客户集中在箱型图下方的箱体中,少数客户分散分布在箱体上界的上方,这部分客户很可能是高价值客户,因为其飞行次数和总飞行公里数明显超过箱体内的其他客户。
(3)客户积分信息分布分析
选取积分兑换次数、总累计积分进行探索分析,探索客户的积分信息分布情况。
1 #7-4 探索客户的积分信息分布情况 2 import pandas as pd 3 import matplotlib.pyplot as plt 4 datafile= 'E:/大三下/数据分析/数据/第七章/air_data.csv' 5 data = pd.read_csv(datafile, encoding = 'utf-8') 6 # 积分信息类别 7 # 提取会员积分兑换次数 8 ec = data['EXCHANGE_COUNT'] 9 # 绘制会员兑换积分次数直方图 10 fig = plt.figure(figsize=(8 ,5)) # 设置画布大小 11 plt.hist(ec, bins=5, color='#0504aa') 12 plt.xlabel('兑换次数') 13 plt.ylabel('会员人数') 14 plt.title('2019114243032 会员兑换积分次数分布直方图') 15 plt.show() 16 plt.close 17 # 提取会员总累计积分 18 ps = data['Points_Sum'] 19 # 绘制会员总累计积分箱型图 20 fig = plt.figure(figsize=(5 ,8)) 21 plt.boxplot(ps, 22 patch_artist=True, 23 labels = ['总累计积分'], # 设置x轴标题 24 boxprops = {'facecolor':'lightblue'}) # 设置填充颜色 25 plt.title('2019114243032 客户总累计积分箱型图') 26 # 显示y坐标轴的底线 27 plt.grid(axis='y') 28 plt.show() 29 plt.close
通过会员兑换积分次数分布直方图可以看出,绝大部分客户的兑换次数在0~10的区间内, 这表示大部分客户都很少进行积分兑换。通过客户总累计积分箱型图可以看出,一部分客户集中在箱体中,少部分客户分散分布在箱体上方,这部分客户的积分要明显高于箱体内的客户的积分。
3、相关性分析
客户信息属性之间存在相关性,选取入会时间、会员卡级别、客户年龄、飞行次数、总飞行公里数、最近一次乘机至结束时长、积分兑换次数、总累计积分属性,通过相关系数矩阵与热力图分析各属性间的相关性。
1 #7-5 相关系数矩阵与热力图 2 import pandas as pd 3 import matplotlib.pyplot as plt 4 from datetime import datetime 5 datafile= 'E:/大三下/数据分析/数据/第七章/air_data.csv' 6 data = pd.read_csv(datafile, encoding = 'utf-8') 7 # 提取属性并合并为新数据集 8 data_corr = data[['FFP_TIER','FLIGHT_COUNT','LAST_TO_END', 9 'SEG_KM_SUM','EXCHANGE_COUNT','Points_Sum']] 10 age1 = data['AGE'].fillna(0) 11 data_corr['AGE'] = age1.astype('int64') 12 ffp = data['FFP_DATE'].apply(lambda x: datetime.strptime(x, '%Y/%m/%d')) 13 ffp_year = ffp.map(lambda x: x.year) 14 data_corr['ffp_year'] = ffp_year 15 16 # 计算相关性矩阵 17 dt_corr = data_corr.corr(method='pearson') 18 print('2019114243032相关性矩阵为:\n',dt_corr) 19 # 绘制热力图 20 import seaborn as sns 21 plt.subplots(figsize=(10, 10)) # 设置画面大小 22 sns.heatmap(dt_corr, annot=True, vmax=1, square=True, cmap='Blues') 23 plt.show() 24 plt.close
(三)数据预处理
1、数据清洗
观察数据发现,原始数据中存在票价为空值、票价最小值为0、折扣率最小值为0、总飞行公里数大于0的记录。票价为空值的数据可能是客户不存在乘机记录造成的。其他的数据可能是客户乘坐0折机票或者积分兑换造成的。由于原始数据量大,这类数据所占比例较小,对于问题影响不大,因此对其进行丢弃处理。同时,在进行数据探索时,发现部分年龄大于100的记录,也进行丢弃处理,具体处理方法如下:1)丢弃票价为空的记录。2)保留票价不为0的,或者平均折扣率不为0且总飞行公里数大于0 的记录。3)丢弃年龄大于100的记录。
使用pandas对满足清洗条件的数据进行丢弃,处理方法为满足清洗条件的一行数据全部丢弃。
1 #7-6清洗空值与异常值 2 import numpy as np 3 import pandas as pd 4 datafile = 'E:/大三下/数据分析/数据/第七章/air_data.csv' # 原始数据路径 5 cleanedfile = 'E:/大三下/数据分析/数据/第七章/data_cleaned.csv' # 数据清洗后保存的文件路径 6 7 # 读取数据 8 airline_data = pd.read_csv(datafile,encoding = 'utf-8') 9 print('原始数据的形状为:', airline_data.shape) 10 11 # 去除票价为空的记录 12 airline_notnull = airline_data.loc[airline_data['SUM_YR_1'].notnull() & airline_data['SUM_YR_2'].notnull(),:] 13 print('删除缺失记录后数据的形状为:', airline_notnull.shape) 14 # 只保留票价非零的,或者平均折扣率不为0且总飞行公里数大于0的记录 15 index1 = airline_notnull['SUM_YR_1'] != 0 16 index2 = airline_notnull['SUM_YR_2'] != 0 17 index3 = (airline_notnull['SEG_KM_SUM']> 0) & (airline_notnull['avg_discount'] != 0) 18 index4 = airline_notnull['AGE'] > 100 # 去除年龄大于100的记录 19 airline = airline_notnull[(index1 | index2) & index3 & ~index4] 20 print('数据清洗后数据的形状为:',airline.shape) 21 airline.to_csv(cleanedfile) # 保存清洗后的数据
2、属性归约
(1)属性选择
本案例的目标是客户价值分析,即通过航空公司客户数据识别不同价值的客户。识别客户价值应用最广泛的模型是RFM模型。本案例将客户关系长度L、消费时间间隔R、消费频率F、飞行里程M和折扣系数的平均值C这5个特征作为航空公司识别客户价值的特征 ,记为LRFMC模型。原始数据中属性太多,根据航空公司客户价值LRFMC模型,选择与LRFMC指标相关的6个属性:FFP_DATE、LOAD_TIME、 FLIGHT_COUNT、AVG_DISCOUNT、SEG_KM_SUM、 LAST_TO_END。删除与其不相关、弱相关或冗余的属性,如会员卡号、性别、工作地城市、工作地所在省份、工作地所在国家、年龄等属性。
1 #7-7 属性选择 2 import pandas as pd 3 import numpy as np 4 # 读取数据清洗后的数据 5 cleanedfile = 'E:/大三下/数据分析/数据/第七章/data_cleaned.csv' # 数据清洗后保存的文件路径 6 airline = pd.read_csv(cleanedfile, encoding='utf-8') 7 # 选取需求属性 8 airline_selection = airline[['FFP_DATE','LOAD_TIME','LAST_TO_END', 9 'FLIGHT_COUNT','SEG_KM_SUM','avg_discount']] 10 print('筛选的属性前5行为:\n',airline_selection.head())
(2)数据变换
1 #7-8属性构造与数据标准化 2 # 构造属性L 3 L = pd.to_datetime(airline_selection['LOAD_TIME']) - \ 4 pd.to_datetime(airline_selection['FFP_DATE']) 5 L = L.astype('str').str.split().str[0] 6 L = L.astype('int')/30 7 # 合并属性 8 airline_features = pd.concat([L,airline_selection.iloc[:,2:]],axis=1) 9 print('构建的LRFMC属性前5行为:\n',airline_features.head()) 10 # 数据标准化 11 from sklearn.preprocessing import StandardScaler 12 data = StandardScaler().fit_transform(airline_features) 13 np.savez('E:/大三下/数据分析/数据/第七章/airline_scale.npz',data) 14 print('标准化后LRFMC 5个属性为:\n',data[:5,:])
(四)模型构建
1、客户聚类
客户价值分析模型构建主要由两个部分构成:第一部分,根据航空公司客户5个指标的数据,对客户作聚类分群。第二部分,结合业务对每个客户群进行特征分析,分析其客户价值,并对每个客户群进行排名。采用K-Means聚类算法对客户数据进行客户分群,聚成5类(需要结合业务的理解与分析来确定客户的类别数量)。 使用scikit-learn库下的聚类子库(sklearn.cluster)可以实现K-Means聚类算法。使用标准化后的数据进行聚类。
1 #7-9 K-Meas聚类标准化后的数据 2 import pandas as pd 3 import numpy as np 4 from sklearn.cluster import KMeans # 导入K-Mmeans算法 5 # 读取标准化后的数据 6 airline_scale = np.load('E:/大三下/数据分析/数据/第七章/airline_scale.npz')['arr_0'] 7 k = 5 # 确定聚类中心数 8 9 # 构建模型,随机种子设为123 10 kmeans_model = KMeans(n_clusters=k, n_jobs=4, random_state=123) 11 fit_kmeans = kmeans_model.fit(airline_scale) # 模型训练 12 13 # 查看聚类结果 14 kmeans_cc = kmeans_model.cluster_centers_ # 聚类中心 15 print('各类聚类中心为:\n',kmeans_cc) 16 kmeans_labels = kmeans_model.labels_ 17 print('各样本的类别标签为:\n',kmeans_labels) # 样本的类别标签 18 r1 = pd.Series(kmeans_model.labels_).value_counts() # 统计不同类别样本的数目 19 print('最终每个类别的数目为:\n',r1) 20 21 # 输出聚类分群的结果 22 cluster_center = pd.DataFrame(kmeans_model.cluster_centers_,\ 23 columns = ['ZL','ZR','ZF','ZM','ZC']) # 将聚类中心放在数据框中 24 cluster_center.index = pd.DataFrame(kmeans_model.labels_ ).\ 25 drop_duplicates().iloc[:,0] # 将样本类别作为数据框索引 26 print(cluster_center)
2、客户价值分析
针对聚类结果进行特征分析,绘制客户分群雷达图。
1 #7-10 绘制客户分群雷达图 2 #%matplotlib inline 3 import matplotlib.pyplot as plt 4 # 客户分群雷达图 5 labels = ['ZL','ZR','ZF','ZM','ZC'] 6 7 cluster_center = pd.DataFrame(kmeans_cc, columns=labels) 8 9 legen = ['客户群' + str(i + 1) for i in cluster_center.index] # 客户群命名 10 lstype = ['-','--',(0, (3, 5, 1, 5, 1, 5)),':','-.'] 11 kinds = list(cluster_center.iloc[:, 0]) 12 # 由于雷达图要保证数据闭合,因此再添加L列,并转换为np.ndarray 13 cluster_center = pd.concat([cluster_center, cluster_center[['ZL']]], axis=1) 14 centers = np.array(cluster_center.iloc[:, 0:]) 15 16 # 分割圆周长,并让其闭合 17 n = len(labels) 18 angle = np.linspace(0, 2 * np.pi, n, endpoint=False) 19 angle = np.concatenate((angle, [angle[0]])) 20 labels = np.concatenate((labels,[labels[0]])) 21 22 # 绘图 23 fig = plt.figure(figsize=(8,6)) # 以极坐标的形式绘制图形 24 ax = fig.add_subplot(111, polar=True) 25 plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签 26 plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号 27 # 画线 28 for i in range(len(kinds)): 29 ax.plot(angle, centers[i], linestyle=lstype[i], linewidth=2, label=kinds[i]) 30 # 添加属性标签 31 ax.set_thetagrids(angle * 180 / np.pi, labels) 32 plt.title('2019114243032 客户特征分析雷达图') 33 plt.legend(legen) 34 plt.show() 35 plt.close
结合业务分析,通过比较各个特征在群间的大小来对某一个群的特征进行评价分析。其中,客户群2在特征C处的值最大,在特征F、M处 的值较小,说明客户群2是偏好乘坐高级舱位的客户群;客户群3在特征F和M上的值最大,且在特征R上的值最小,说明客户群3的会员频繁乘机且近期都有乘机记录;客户群5在特征R处的值最大,在特征L、F、 M和C处的值都较小,说明客户群5已经很久没有乘机,是入会时间较短的低价值的客户群;客户群1在所有特征上的值都很小,且在特征L处的值最小,说明客户群1属于新入会员较多的客户群;客户群4在特征L处的值最大,在特征R处的值较小,其他特征值都比较适中,说明客户群4 入会时间较长,飞行频率也较高,是有较高价值的客户群。
(五)模型应用
根据对各个客户群进行特征分析,可以采取下面的一些营销手段和策略,为航空公司的价值客户群管理提供参考。
1、会员的升级与保级
航空公司的会员可以分为白金卡会员、金卡会员、银卡会员、普通卡会员等,其中非普通卡会员可以统称为航空公司的精英会员。虽然各个航空公司都有自己的特点和规定,但会员制的管理方法大同小异。成为精英会员一般都要求在一定时间内(如一年)积累一定的飞行里程或航段,达到这种要求后就会在有效期内(通常为两年)成为精英会员,并享受相应的高级别服务。有效期快结束时,根据相关评价方法确定客户是否有资格继续作为精英会员,然后对该客户进行相应的升级或降级。
2.首次兑换
航空公司常旅客计划中最吸引客户的内容就是客户可以通过消费积累的里程来兑换免票或免费升舱等。从数据库中提取出接近但尚未达到首次兑换标准的会员信息,对他们进行适当提醒或采取一些促销活动,使他们通过消费达到兑换标准。一旦实现了首次兑换,客户在本公司进行再次消费兑换就比在其他公司进行首次兑换要容易许多,等于在一定程度上提高了转移的成本。另外,在一些特殊的时间点(如里程折半的时间点)之前可以给客户一些提醒,这样可以增加客户的满意度。
3.交叉销售
通过发行“联名卡”等与非航空类企业的合作,使客户在其他企业的 消费过程中获得本公司的积分,增强与公司的联系,提高他们的忠诚度。
三、拓展思考
在国内航空市场竞争日益激烈的背景下,航空公司在客户流失方面应该引起足够的重视。如何改善流失问题继而提高客户满意度、忠诚度是航空公司维护自身市场并面对激烈竞争的一件大事,客户流失分析将成为帮助航空公司开展持续改进活动的指南。
客户流失分析可以针对目前老客户进行分类预测。针对航空公司客户信息数据(见demo/data/air_data.csv),可以进行老客户以及客户类型的定义(其中,将飞行次数大于6次的客户定义为老客户,将第二年飞行次数与第一年飞行次数比例小于50%的客户定义为已流失客户;将 第二年飞行次数与第一年飞行次数比例在区间[50%,90%)内的客户定义为准流失客户;将第二年飞行次数与第一年飞行次数比例大于90%的 客户定义为未流失客户)。同时,需要选取客户信息中的关键属性,如会员卡级别、客户类型(流失、准流失、未流失)、平均乘机时间间隔、平均折扣系数、积分兑换次数、非乘机积分总和、单位里程票价、 单位里程积分等。随机选取数据的80%作为分类的训练样本,剩余的 20%作为测试样本。构建客户的流失模型,运用模型预测未来客户的类别归属(未流失、准流失,或已流失)。
1、特征选择
这里直接采用之前清洗好的数据集来进行特征选择,这里选择的关键属性有:会员卡级别、客户类型、平均乘机时间间隔、平均折扣率、积分兑换次数、非乘机积分总和、单位里程票价以及单位里程积分等。其中客户类型需要进行筛选定义,单位里程票价和单位里程积分需要进行计算。
1 import pandas as pd 2 #读数据 3 input_file = 'E:/大三下/数据分析/数据/第七章/data_cleaned.xlsx' 4 output_file = 'E:/大三下/数据分析/数据/第七章/selected.xls' 5 data = pd.read_excel(input_file) 6 #选取特征 7 data['单位里程票价'] = (data['SUM_YR_1'] + data['SUM_YR_2'])/data['SEG_KM_SUM'] 8 data['单位里程积分'] = (data['P1Y_BP_SUM'] + data['L1Y_BP_SUM'])/data['SEG_KM_SUM'] 9 data['飞行次数比例'] = data['L1Y_Flight_Count'] / data['P1Y_Flight_Count'] #第二年飞行次数与第一年飞行次数的比例 10 #筛选出老客户(飞行次数大于6次的为老客户) 11 data = data[data['FLIGHT_COUNT'] > 6] 12 #选择特征 13 data = data[['FFP_TIER','飞行次数比例','AVG_INTERVAL', 14 'avg_discount','EXCHANGE_COUNT','Eli_Add_Point_Sum','单位里程票价','单位里程积分']] 15 #导出 16 data.to_excel(output_file,index=None)
然后进行客户类别的定义添加:
1 import pandas as pd 2 input_file = 'E:/大三下/数据分析/数据/第七章/selected.xls' 3 output_file = 'E:/大三下/数据分析/数据/第七章/classfication.xls' 4 data = pd.read_excel(input_file) 5 data['客户类型'] = None 6 for i in range(len(data)): 7 #第一、二年飞行次数比例小于50%的客户定义为已流失 8 if data['飞行次数比例'][i] < 0.5: 9 data['客户类型'][i] = 0 #0代表已流失 10 #第一、二年飞行次数比例在[0.5,0.9)之间的客户定义为准流失 11 if (data['飞行次数比例'][i] >= 0.5) & (data['飞行次数比例'][i] < 0.9) : 12 data['客户类型'][i] = 1 #1代表准流失 13 #第一、二年飞行次数比例大于等于90%的客户定义为未流失 14 if data['飞行次数比例'][i] >= 0.9: 15 data['客户类型'][i] = 2 #2代表未流失 16 #导出 17 data.to_excel(output_file,index=None)
2、标准化处理
1 import pandas as pd 2 #读数 3 input_file = 'E:/大三下/数据分析/数据/第七章/classfication.xls' 4 output_file = 'E:/大三下/数据分析/数据/第七章/std.xls' 5 data = pd.read_excel(input_file) 6 #去掉飞行次数比例 7 data = data[['FFP_TIER','AVG_INTERVAL','avg_discount','EXCHANGE_COUNT', 8 'Eli_Add_Point_Sum','单位里程票价','单位里程积分','客户类型']] 9 #标准化 10 data.loc[:,:'单位里程积分'] = (data.loc[:,:'单位里程积分'] - data.loc[:,:'单位里程积分'].mean(axis = 0)) \ 11 / (data.loc[:,:'单位里程积分'].std(axis = 0)) 12 #导出 13 data.to_excel(output_file,index=None)
3、模型选择
主要对两个算法进行了测试,分别是决策树以及SVM算法。采用了交叉验证的方法,来测试哪个模型表现得好。
1 import pandas as pd 2 from sklearn.model_selection import cross_val_score 3 from sklearn.tree import DecisionTreeClassifier 4 from sklearn.svm import SVC 5 input_file = 'E:/大三下/数据分析/数据/第七章/std.xls' 6 data = pd.read_excel(input_file) 7 #划分X,y 8 X = data.loc[:,:'单位里程积分'].values 9 y = data.loc[:,'客户类型'].values 10 #模型选择使用交叉验证法来评估模型 11 model1 = DecisionTreeClassifier() 12 model2 = SVC(kernel='rbf') 13 score1 = cross_val_score(model1,X,y,cv=5) 14 score2 = cross_val_score(model2,X,y,cv=5) 15 print('决策树模型得分:{:.2f}'.format(score1.mean())) 16 print('SVM模型得分:{:.2f}'.format(score2.mean()))
可以看到在还没有对SVM进行参数选择优化的时候,SVM得分已经远远超过了决策树,所以在本次流失分析中,初步选择SVM模型进行此次的分类模型训练。
4、模型参数选择
使用网格搜索法来选取SVM的最优参数,即确定C、gamma的值。
1 import pandas as pd 2 from sklearn.model_selection import train_test_split 3 from sklearn.model_selection import GridSearchCV 4 from sklearn.svm import SVC 5 import joblib 6 #读取数据 7 input_file = 'E:/大三下/数据分析/数据/第七章/std.xls' 8 output_file = 'E:/大三下/数据分析/数据/第七章/loss.pkl' 9 data = pd.read_excel(input_file) 10 #划分训练集、测试集 11 X = data.loc[:,:'单位里程积分'].values 12 y = data.loc[:,'客户类型'].values 13 X_train,X_test,y_train,y_test = train_test_split(X,y,train_size = 0.8) 14 #采用网格搜索法来寻找SVC的最优参数 15 svc = SVC(kernel='rbf') 16 params = {'gamma':[0.1,1.0,10.0], 17 'C':[1.0,10.0,100.0]} 18 grid_search = GridSearchCV(svc,params,cv=5) 19 grid_search.fit(X_train,y_train) 20 print('模型最高分 {:.2f}'.format(grid_search.score(X_test,y_test))) 21 print('最优参数为: {}'.format(grid_search.best_params_)) 22 23 svc = SVC(kernel='rbf',C=1.0,gamma=1.0) 24 svc.fit(X_train,y_train) 25 joblib.dump(svc,output_file)
5、模型预测
1 import joblib 2 from model import X_test,y_test 3 #导入模型 4 model = joblib.load('E:/大三下/数据分析/数据/第七章/loss.pkl') 5 #预测分类 6 y_predict = model.predict([X_test[0]]) 7 print(y_predict) 8 print(y_test[0])
如图所示,这一组预测是正确的,预测的结果是2代表未流失,实际结果也是未流失,说明预测正确,这次的模型得分不高,可以看采用什么办法来提高模型得分。
标签:plt,航空公司,客户,会员,pd,import,价值,data From: https://www.cnblogs.com/52183-717/p/17190747.html