面对激烈的市场竞争,各个航空公司相继推出了更优惠的营销方式来吸引更多的客户,国内某航空公司面临着常旅客流失、竞争力下降和航空资源未充分利用等经营危机。通过建立合理的客户价值评估模型,对客户进行分类,分析比较不同客户群体的价值,并制定相应的营销策略,对不同的客户群提供个性化的客户服务是必须的和有效的。结合该航空公司已累积的大量的会员档案信息和其乘坐航班记录,实现以下目标:
1)借助航空公司客户数据,对客户进行分类。
2)对不同的客户类别进行特征分析,比较不同类别的客户的价值。
3)针对不同价值的客户类别制定相应的营销策略,为其提供个性化服务。
二、分析方法与过程
在客户价值分析领域,最具影响力并得到实证检验的理论与模型有:客户终生价值理论、客户价值金字塔模型、策略评估矩阵分析法和RFM客户价值分析模型等。
(一)分析步骤与流程
航空公司客户价值分析案例的总体流程如图所示,主要包括以下4个步骤:
1)抽取航空公司2012年4月1日至2014年3月31日的数据。
2)对抽取的数据进行数据探索分析与预处理,包括数据缺失值与异常值的探索分析、数据清洗、特征构建、标准化等操作。
3)基于RFM模型,使用K-Means算法进行客户分群。
4)针对模型结果得到不同价值的客户,采用不同的营销手段,提供定制化的服务。
(二)数据探索分析
1、描述性统计分析
通过对原始数据观察发现数据中存在票价为空值的记录,同时存在票价最小值为0、折扣率最小值为0但总飞行公里数大于0的记录。票价为空值的数据可能是客户不存在乘机记录造成的。其他的数据可能是客户乘坐0折机票或者积分兑换造成的。
首先查找每列属性观测值中空值个数、最大值、最小值。
1#7-1数据探索23#对数据进行基本的探索4#返回缺失值个数以及最大、最小值5importpandasaspd6datafile='E:/大三下/数据分析/数据/第七章/air_data.csv'#航空原始数据,第一行为属性标签7resultfile='E:/大三下/数据分析/数据/第七章/explore.csv'#数据探索结果表89#读取原始数据,指定UTF-8编码(需要用文本编辑器将数据转换为UTF-8编码)10data=pd.read_csv(datafile,encoding='utf-8')1112#包括对数据的基本描述,percentiles参数是指定计算多少的分位数表(如1/4分位数、中位数等)13explore=data.describe(percentiles=[],include='all').T14#describe()函数自动计算非空值数,需要手动计算空值数15explore['null']=len(data)-explore['count']1617explore=explore[['null','max','min']]18explore.columns=[u'空值数',u'最大值',u'最小值']#表头重命名19'''20这里只选取部分探索结果。describe()函数自动计算的字段有count(非空值数)、21unique(唯一值数)、top(频数最高者)、freq(最高频数)、mean(平均值)、std(方差)、22min(最小值)、50%(中位数)、max(最大值)'''2324explore.to_csv(resultfile)#导出结果根据代码7-1得到的探索结果为下表。
2、分布分析
分别从客户基本信息、乘机信息、积分信息3个角度进行数据探索,寻找客户信息的分布规律。
(1)客户基本信息分布分析
由会员性别比例饼图可看出:男性会员明显比女性会员多。
由会员各级别人数条形图可看出:绝大部分会员为4级会员,仅有少数会员为5级会员或6级会员。
由会员年龄分布箱型图可看出:大部分会员年龄集中在30-50岁之间,极少量的会员年龄小于20岁或高于60岁,且存在一个超过100岁的异常数据。
(2)客户乘机信息分布分析
选取最后一次乘机至结束的时长、客户乘机信息中的飞行次数、总飞行公里数进行探索分析,探索客户的乘机信息分布情况。
根据会员最后一次乘机至结束的时长箱型图,客户的入会时长主要分布在50~300区间内,另外有一部分客户群体的入会时长分布在600以上的区间,可分为两个群体。根据客户飞行次数分布箱型图和客户总飞行公里数箱型图,客户的飞行次数与总飞行公里数也明显地分为两个群体,大部分客户集中在箱型图下方的箱体中,少数客户分散分布在箱体上界的上方,这部分客户很可能是高价值客户,因为其飞行次数和总飞行公里数明显超过箱体内的其他客户。
(3)客户积分信息分布分析
选取积分兑换次数、总累计积分进行探索分析,探索客户的积分信息分布情况。
通过会员兑换积分次数分布直方图可以看出,绝大部分客户的兑换次数在0~10的区间内,这表示大部分客户都很少进行积分兑换。通过客户总累计积分箱型图可以看出,一部分客户集中在箱体中,少部分客户分散分布在箱体上方,这部分客户的积分要明显高于箱体内的客户的积分。
(三)数据预处理
1、数据清洗
观察数据发现,原始数据中存在票价为空值、票价最小值为0、折扣率最小值为0、总飞行公里数大于0的记录。票价为空值的数据可能是客户不存在乘机记录造成的。其他的数据可能是客户乘坐0折机票或者积分兑换造成的。由于原始数据量大,这类数据所占比例较小,对于问题影响不大,因此对其进行丢弃处理。同时,在进行数据探索时,发现部分年龄大于100的记录,也进行丢弃处理,具体处理方法如下:1)丢弃票价为空的记录。2)保留票价不为0的,或者平均折扣率不为0且总飞行公里数大于0的记录。3)丢弃年龄大于100的记录。
使用pandas对满足清洗条件的数据进行丢弃,处理方法为满足清洗条件的一行数据全部丢弃。
1#7-6清洗空值与异常值2importnumpyasnp3importpandasaspd4datafile='E:/大三下/数据分析/数据/第七章/air_data.csv'#原始数据路径5cleanedfile='E:/大三下/数据分析/数据/第七章/data_cleaned.csv'#数据清洗后保存的文件路径67#读取数据8airline_data=pd.read_csv(datafile,encoding='utf-8')9print('原始数据的形状为:',airline_data.shape)1011#去除票价为空的记录12airline_notnull=airline_data.loc[airline_data['SUM_YR_1'].notnull()&airline_data['SUM_YR_2'].notnull(),:]13print('删除缺失记录后数据的形状为:',airline_notnull.shape)14#只保留票价非零的,或者平均折扣率不为0且总飞行公里数大于0的记录15index1=airline_notnull['SUM_YR_1']!=016index2=airline_notnull['SUM_YR_2']!=017index3=(airline_notnull['SEG_KM_SUM']>0)&(airline_notnull['avg_discount']!=0)18index4=airline_notnull['AGE']>100#去除年龄大于100的记录19airline=airline_notnull[(index1|index2)&index3&~index4]20print('数据清洗后数据的形状为:',airline.shape)21airline.to_csv(cleanedfile)#保存清洗后的数据2、属性归约
(1)属性选择
(2)数据变换
(四)模型构建
1、客户聚类
客户价值分析模型构建主要由两个部分构成:第一部分,根据航空公司客户5个指标的数据,对客户作聚类分群。第二部分,结合业务对每个客户群进行特征分析,分析其客户价值,并对每个客户群进行排名。采用K-Means聚类算法对客户数据进行客户分群,聚成5类(需要结合业务的理解与分析来确定客户的类别数量)。使用scikit-learn库下的聚类子库(sklearn.cluster)可以实现K-Means聚类算法。使用标准化后的数据进行聚类。
1#7-9K-Meas聚类标准化后的数据2importpandasaspd3importnumpyasnp4fromsklearn.clusterimportKMeans#导入K-Mmeans算法5#读取标准化后的数据6airline_scale=np.load('E:/大三下/数据分析/数据/第七章/airline_scale.npz')['arr_0']7k=5#确定聚类中心数89#构建模型,随机种子设为12310kmeans_model=KMeans(n_clusters=k,n_jobs=4,random_state=123)11fit_kmeans=kmeans_model.fit(airline_scale)#模型训练1213#查看聚类结果14kmeans_cc=kmeans_model.cluster_centers_#聚类中心15print('各类聚类中心为:\n',kmeans_cc)16kmeans_labels=kmeans_model.labels_17print('各样本的类别标签为:\n',kmeans_labels)#样本的类别标签18r1=pd.Series(kmeans_model.labels_).value_counts()#统计不同类别样本的数目19print('最终每个类别的数目为:\n',r1)2021#输出聚类分群的结果22cluster_center=pd.DataFrame(kmeans_model.cluster_centers_,\23columns=['ZL','ZR','ZF','ZM','ZC'])#将聚类中心放在数据框中24cluster_center.index=pd.DataFrame(kmeans_model.labels_).\25drop_duplicates().iloc[:,0]#将样本类别作为数据框索引26print(cluster_center)2、客户价值分析
针对聚类结果进行特征分析,绘制客户分群雷达图。
(五)模型应用
根据对各个客户群进行特征分析,可以采取下面的一些营销手段和策略,为航空公司的价值客户群管理提供参考。
1、会员的升级与保级
2.首次兑换
3.交叉销售
通过发行“联名卡”等与非航空类企业的合作,使客户在其他企业的消费过程中获得本公司的积分,增强与公司的联系,提高他们的忠诚度。
三、拓展思考
在国内航空市场竞争日益激烈的背景下,航空公司在客户流失方面应该引起足够的重视。如何改善流失问题继而提高客户满意度、忠诚度是航空公司维护自身市场并面对激烈竞争的一件大事,客户流失分析将成为帮助航空公司开展持续改进活动的指南。
1、特征选择
1importpandasaspd2#读数据3input_file='E:/大三下/数据分析/数据/第七章/data_cleaned.xlsx'4output_file='E:/大三下/数据分析/数据/第七章/selected.xls'5data=pd.read_excel(input_file)6#选取特征7data['单位里程票价']=(data['SUM_YR_1']+data['SUM_YR_2'])/data['SEG_KM_SUM']8data['单位里程积分']=(data['P1Y_BP_SUM']+data['L1Y_BP_SUM'])/data['SEG_KM_SUM']9data['飞行次数比例']=data['L1Y_Flight_Count']/data['P1Y_Flight_Count']#第二年飞行次数与第一年飞行次数的比例10#筛选出老客户(飞行次数大于6次的为老客户)11data=data[data['FLIGHT_COUNT']>6]12#选择特征13data=data[['FFP_TIER','飞行次数比例','AVG_INTERVAL',14'avg_discount','EXCHANGE_COUNT','Eli_Add_Point_Sum','单位里程票价','单位里程积分']]15#导出16data.to_excel(output_file,index=None)
然后进行客户类别的定义添加:
1importpandasaspd2input_file='E:/大三下/数据分析/数据/第七章/selected.xls'3output_file='E:/大三下/数据分析/数据/第七章/classfication.xls'4data=pd.read_excel(input_file)5data['客户类型']=None6foriinrange(len(data)):7#第一、二年飞行次数比例小于50%的客户定义为已流失8ifdata['飞行次数比例'][i]<0.5:9data['客户类型'][i]=0#0代表已流失10#第一、二年飞行次数比例在[0.5,0.9)之间的客户定义为准流失11if(data['飞行次数比例'][i]>=0.5)&(data['飞行次数比例'][i]<0.9):12data['客户类型'][i]=1#1代表准流失13#第一、二年飞行次数比例大于等于90%的客户定义为未流失14ifdata['飞行次数比例'][i]>=0.9:15data['客户类型'][i]=2#2代表未流失16#导出17data.to_excel(output_file,index=None)2、标准化处理
1importpandasaspd2#读数3input_file='E:/大三下/数据分析/数据/第七章/classfication.xls'4output_file='E:/大三下/数据分析/数据/第七章/std.xls'5data=pd.read_excel(input_file)6#去掉飞行次数比例7data=data[['FFP_TIER','AVG_INTERVAL','avg_discount','EXCHANGE_COUNT',8'Eli_Add_Point_Sum','单位里程票价','单位里程积分','客户类型']]9#标准化10data.loc[:,:'单位里程积分']=(data.loc[:,:'单位里程积分']-data.loc[:,:'单位里程积分'].mean(axis=0))\11/(data.loc[:,:'单位里程积分'].std(axis=0))12#导出13data.to_excel(output_file,index=None)3、模型选择
主要对两个算法进行了测试,分别是决策树以及SVM算法。采用了交叉验证的方法,来测试哪个模型表现得好。
可以看到在还没有对SVM进行参数选择优化的时候,SVM得分已经远远超过了决策树,所以在本次流失分析中,初步选择SVM模型进行此次的分类模型训练。
4、模型参数选择
使用网格搜索法来选取SVM的最优参数,即确定C、gamma的值。
1importpandasaspd2fromsklearn.model_selectionimporttrain_test_split3fromsklearn.model_selectionimportGridSearchCV4fromsklearn.svmimportSVC5importjoblib6#读取数据7input_file='E:/大三下/数据分析/数据/第七章/std.xls'8output_file='E:/大三下/数据分析/数据/第七章/loss.pkl'9data=pd.read_excel(input_file)10#划分训练集、测试集11X=data.loc[:,:'单位里程积分'].values12y=data.loc[:,'客户类型'].values13X_train,X_test,y_train,y_test=train_test_split(X,y,train_size=0.8)14#采用网格搜索法来寻找SVC的最优参数15svc=SVC(kernel='rbf')16params={'gamma':[0.1,1.0,10.0],17'C':[1.0,10.0,100.0]}18grid_search=GridSearchCV(svc,params,cv=5)19grid_search.fit(X_train,y_train)20print('模型最高分{:.2f}'.format(grid_search.score(X_test,y_test)))21print('最优参数为:{}'.format(grid_search.best_params_))2223svc=SVC(kernel='rbf',C=1.0,gamma=1.0)24svc.fit(X_train,y_train)25joblib.dump(svc,output_file)5、模型预测
1importjoblib2frommodelimportX_test,y_test3#导入模型4model=joblib.load('E:/大三下/数据分析/数据/第七章/loss.pkl')5#预测分类6y_predict=model.predict([X_test[0]])7print(y_predict)8print(y_test[0])如图所示,这一组预测是正确的,预测的结果是2代表未流失,实际结果也是未流失,说明预测正确,这次的模型得分不高,可以看采用什么办法来提高模型得分。