查看原文
其他

R语言之航空客户价值聚类分析

2017-07-27 人和六栋 R语言中文社区

作者:人和六栋    R语言中文社区专栏特邀作者

博客专栏:https://ask.hellobi.com/blog/renhe6dong


航空客户价值分析不同于传统的RFM模型,其考虑了5个因素:入会时长L,消费时间间隔R,消费频率F,飞行里程M,和折扣系数的平均值C,简记为LRFMC模型,通过对这5个变量对应下的观测数据进行聚类,从而将客户分成不同价值等级的群体。

##读入数据

>airdata<-read.csv("E:\\R语言\\图书配套数据、代码\\chapter7\\上机实验\\data\\air_data.csv",header=T)

说明:共有62988条记录,44个变量

>names(airdata)

[1] "MEMBER_NO"               "FFP_DATE"                "FIRST_FLIGHT_DATE"      
[4] "GENDER"                  "FFP_TIER"                "WORK_CITY"              
[7] "WORK_PROVINCE"           "WORK_COUNTRY"            "AGE"                    
[10] "LOAD_TIME"               "FLIGHT_COUNT"            "BP_SUM"                
[13] "EP_SUM_YR_1"             "EP_SUM_YR_2"             "SUM_YR_1"              
[16] "SUM_YR_2"                "SEG_KM_SUM"              "WEIGHTED_SEG_KM"        
[19] "LAST_FLIGHT_DATE"        "AVG_FLIGHT_COUNT"        "AVG_BP_SUM"            
[22] "BEGIN_TO_FIRST"          "LAST_TO_END"             "AVG_INTERVAL"          
[25] "MAX_INTERVAL"            "ADD_POINTS_SUM_YR_1"     "ADD_POINTS_SUM_YR_2"    
[28] "EXCHANGE_COUNT"          "avg_discount"            "P1Y_Flight_Count"      
[31] "L1Y_Flight_Count"        "P1Y_BP_SUM"              "L1Y_BP_SUM"            
[34] "EP_SUM"                  "ADD_Point_SUM"           "Eli_Add_Point_Sum"      
[37] "L1Y_ELi_Add_Points"      "Points_Sum"              "L1Y_Points_Sum"        
[40] "Ration_L1Y_Flight_Count" "Ration_P1Y_Flight_Count" "Ration_P1Y_BPS"        
[43] "Ration_L1Y_BPS"          "Point_NotFlight"

##选择需要的变量

由于变量个数很多,许多都是分析中不需要的,可以选择性的对可能需要的变量进行探索性分析。

>airdatanew<-airdata[,c(1:2,10:11,15:18,20:29)]#实际的选择可以自己确定,但是涉及到LRFMC模型的变量一定要选进来。

说明:由于本分析中不涉及客户特征相关的分析,所以可以剔除。另外积分相关的数据也不涉及可以剔除。

##数据探索

>summary(airdatanew)

  MEMBER_NO           FFP_DATE         LOAD_TIME      FLIGHT_COUNT       SUM_YR_1    
Min.   :    1   2011/1/13 :  184   2014/3/31:62988   Min.   :  2.00   Min.   :     0  
1st Qu.:15748   2013/1/1  :  165                     1st Qu.:  3.00   1st Qu.:  1003  
Median :31495   2013/3/1  :  100                     Median :  7.00   Median :  2800  
Mean   :31495   2010/11/17:   99                     Mean   : 11.84   Mean   :  5355  
3rd Qu.:47241   2011/1/14 :   95                     3rd Qu.: 15.00   3rd Qu.:  6574  
Max.   :62988   2012/9/19 :   88                     Max.   :213.00   Max.   :239560  
                (Other)   :62257                                      NA's   :551    
   SUM_YR_2        SEG_KM_SUM     WEIGHTED_SEG_KM  AVG_FLIGHT_COUNT    AVG_BP_SUM    
Min.   :     0   Min.   :   368   Min.   :     0   Min.   : 0.2500   Min.   :    0.0  
1st Qu.:   780   1st Qu.:  4747   1st Qu.:  3219   1st Qu.: 0.4286   1st Qu.:  336.0  
Median :  2773   Median :  9994   Median :  6978   Median : 0.8750   Median :  752.4  
Mean   :  5604   Mean   : 17124   Mean   : 12777   Mean   : 1.5422   Mean   : 1421.4  
3rd Qu.:  6846   3rd Qu.: 21271   3rd Qu.: 15300   3rd Qu.: 1.8750   3rd Qu.: 1690.3  
Max.   :234188   Max.   :580717   Max.   :558440   Max.   :26.6250   Max.   :63163.5  
NA's   :138                                                                          
BEGIN_TO_FIRST   LAST_TO_END     AVG_INTERVAL     MAX_INTERVAL ADD_POINTS_SUM_YR_1
Min.   :  0.0   Min.   :  1.0   Min.   :  0.00   Min.   :  0   Min.   :     0.0  
1st Qu.:  9.0   1st Qu.: 29.0   1st Qu.: 23.37   1st Qu.: 79   1st Qu.:     0.0  
Median : 50.0   Median :108.0   Median : 44.67   Median :143   Median :     0.0  
Mean   :120.1   Mean   :176.1   Mean   : 67.75   Mean   :166   Mean   :   540.3  
3rd Qu.:166.0   3rd Qu.:268.0   3rd Qu.: 82.00   3rd Qu.:228   3rd Qu.:     0.0  
Max.   :729.0   Max.   :731.0   Max.   :728.00   Max.   :728   Max.   :600000.0  
                                                                                 
ADD_POINTS_SUM_YR_2 EXCHANGE_COUNT     avg_discount  
Min.   :     0.0    Min.   : 0.0000   Min.   :0.0000  
1st Qu.:     0.0    1st Qu.: 0.0000   1st Qu.:0.6120  
Median :     0.0    Median : 0.0000   Median :0.7119  
Mean   :   814.7    Mean   : 0.3198   Mean   :0.7216  
3rd Qu.:     0.0    3rd Qu.: 0.0000   3rd Qu.:0.8095  
Max.   :728282.0    Max.   :46.0000   Max.   :1.5000  
                                                     

说明:

1、只有SUM_YR_1和SUM_YR_2存在缺失值

2、 删除票价为0,但是平均折扣和总飞行公里数大于0的记录(逻辑错误值)

>str(airdatanew)#全部是连续型变量

'data.frame': 62988 obs. of  18 variables:
$ MEMBER_NO          : int  54993 28065 55106 21189 39546 56972 44924 22631 32197 31645 ...
$ FFP_DATE           : Factor w/ 3068 levels "2004/11/1","2004/11/10",..: 498 923 913 1473 1703 1279 590 2095 2519 2183 ...
$ LOAD_TIME          : Factor w/ 1 level "2014/3/31": 1 1 1 1 1 1 1 1 1 1 ...
$ FLIGHT_COUNT       : int  210 140 135 23 152 92 101 73 56 64 ...
$ SUM_YR_1           : num  239560 171483 163618 116350 124560 ...
$ SUM_YR_2           : int  234188 167434 164982 125500 130702 76946 114469 114971 87401 60267 ...
$ SEG_KM_SUM         : int  580717 293678 283712 281336 309928 294585 287042 287230 321489 375074 ...
$ WEIGHTED_SEG_KM    : num  558440 367777 355967 306901 300834 ...
$ AVG_FLIGHT_COUNT   : num  26.25 17.5 16.88 2.88 19 ...
$ AVG_BP_SUM         : num  63164 45310 43895 42164 34231 ...
$ BEGIN_TO_FIRST     : int  2 2 10 21 3 11 11 0 7 2 ...
$ LAST_TO_END        : int  1 7 11 97 5 79 1 3 6 15 ...
$ AVG_INTERVAL       : num  3.48 5.19 5.3 27.86 4.79 ...
$ MAX_INTERVAL       : int  18 17 18 73 47 52 28 45 94 73 ...
$ ADD_POINTS_SUM_YR_1: int  3352 0 3491 0 0 0 0 0 0 0 ...
$ ADD_POINTS_SUM_YR_2: int  36640 12000 12000 0 22704 2460 12320 9500 500 0 ...
$ EXCHANGE_COUNT     : int  34 29 20 11 27 10 20 7 5 13 ...
$ avg_discount       : num  0.962 1.252 1.255 1.091 0.971 ...

说明:

FFP_DATE 和LOAD_TIME 都是因子,后面构建模型前需要将其转化为date格式,计算日期差。

#查看缺失值

>library(mice)

>library(VIM)

>md.pattern(airdatanew)

     MEMBER_NO FFP_DATE LOAD_TIME FLIGHT_COUNT SEG_KM_SUM WEIGHTED_SEG_KM AVG_FLIGHT_COUNT AVG_BP_SUM BEGIN_TO_FIRST LAST_TO_END AVG_INTERVAL
62299         1        1         1            1          1               1                1          1              1           1            1
 551         1        1         1            1          1               1                1          1              1           1            1
 138         1        1         1            1          1               1                1          1              1           1            1
             0        0         0            0          0               0                0          0              0           0            0
     MAX_INTERVAL ADD_POINTS_SUM_YR_1 ADD_POINTS_SUM_YR_2 EXCHANGE_COUNT avg_discount SUM_YR_2 SUM_YR_1    
62299            1                   1                   1              1            1        1        1   0
 551            1                   1                   1              1            1        1        0   1
 138            1                   1                   1              1            1        0        1   1
                0                   0                   0              0            0      138      551 689

>aggr(airdatanew,prop=F,numbers=T)

说明

说明:只有两个变量有缺失值,且缺失值个数为138+551,较之于整体观测记录非常小可以直接删除

#缺失值和不符逻辑值处理

#删除缺失值

>airdatanew<-airdatanew[complete.cases(airdatanew),]#保留完整观测行

#去除逻辑值异常的观测,即删除票价为0,但是平均折扣和总飞行公里数大于0的记录

>index<-which(airdatanew$SUM_YR_1==0&airdatanew$SUM_YR_2==0&airdatanew$avg_discount!=0&airdatanew$SEG_KM_SUM>0)

>airdatanew<-airdatanew[-index,]

说明:删除缺失值和逻辑错误值后,剩下62051个观测

##属性规约:根据LRFMC模型挑选有用的变量

>airdatanew<-airdatanew[,c("MEMBER_NO","FFP_DATE","LOAD_TIME","LAST_TO_END","FLIGHT_COUNT","SEG_KM_SUM","avg_discount")]

>DT::datatable(airdatanew)

说明:至此,分析所需变量以筛选和清洗出来,但是挑选出来的变量要带入模型需要进行变量转换。

##数据变换

#L="LOAD_TIME"-"FFP_DATE"(观测窗口的结束时间-入会时间)(单位:月)

#R="LAST_TO_END"(最后一次乘机时间至观测窗口末端时间长)(单位:月)

#F="FLIGHT_COUNT"(观测窗口内的飞行次数)(单位:次)

#M="SEG_KM_SUM"(观测窗口的总飞行公里数)(单位:公里)

#C="avg_discount"(平均折扣率)

>airdatanew$FFP_DATE<-as.Date(airdatanew$FFP_DATE)#由于是因子变量,需要进行日期转换

>airdatanew$LOAD_TIME<-as.Date(airdatanew$LOAD_TIME)

>airdatanew$L<-as.numeric(round((airdatanew$LOAD_TIME-airdatanew$FFP_DATE)/30,3))#两日期相减得出的是天数,因而需要转化为月份数,这种转换可能和实际月份数有差别,但是不大。

>names(airdatanew)[4:7]<-c("R","F","M","C")#更改变量名

##采用多种方法对数据进行预处理

#将数据标准化处理

>airdata_scale<-scale(airdatanew[,-c(1:3)])#删除"MEMBER_NO","FFP_DATE","LOAD_TIME"这3个字段,剩余字段构建模型

>summary(airdata_scale)

#将数据进行归一化处理

>library(caret)

>airdata_range<-preProcess(airdatanew[,-c(1:3)],method = c("range"))

>airdata_range_pre<-predict(airdata_range,airdatanew[,-c(1:3)])

#将数据进行中心化处理

>airdata_center<-preProcess(airdatanew[,-c(1:3)],method = c("center"))

>airdata_center_pre<-predict(airdata_center,airdatanew[,-c(1:3)])#数据中心化是数据标准化的步骤之一,即x-均值,其并没有消除量纲的影响。

##聚类分析构建模型

>fit_kmeans_scale<-kmeans(airdata_scale,5)

>fit_kmeans_range<-kmeans(airdata_range_pre,5)

>fit_kmeans_center<-kmeans(airdata_center_pre,5)

#得出每个类别的中心

>centers_scale<-as.data.frame(fit_kmeans_scale$centers)

         R           F           M          C          L
1 -0.37732916 -0.08717321 -0.09498699 -0.1557095  1.1604978
2  1.68554920 -0.57392324 -0.53674300 -0.1743790 -0.3137005
3 -0.41494899 -0.16116894 -0.16107783 -0.2530821 -0.7003074
4 -0.79944875  2.48351216  2.42472275  0.3087468  0.4829613
5 -0.00249783 -0.22544385 -0.22944009  2.1972694  0.0554208

>centers_range<-as.data.frame(fit_kmeans_range$centers)#归一化处理后,虽然数据都在0-1之间分布,但是从结果可以看出不同类别之间的区分度降低,特征反而不明显了。

  R          F          M         C         L
1 0.63233743 0.01032082 0.01091188 0.4740049 0.1604486
2 0.09778936 0.07880935 0.04507924 0.4997665 0.7739829
3 0.60450929 0.01269875 0.01161781 0.4840201 0.6438978
4 0.12500165 0.04596936 0.02873297 0.4708241 0.1267417
5 0.11229993 0.06062228 0.03554612 0.4866022 0.4397122

>centers_center<-as.data.frame(fit_kmeans_center$centers)#结果可以看出其并没有消除量纲的影响,因而效果比较差,接下来不用考虑。

 R         F          M            C         L
1 -144.93048 39.941543  64949.181  0.066787595 14.960921
2 -121.84085 18.093129  27394.168  0.030237551  8.645472
3   60.14267 -7.000593 -10964.442 -0.011601076 -3.325117
4 -151.46053 63.959112 141851.836  0.124879307 20.491782
5  -73.68072  3.136913   4054.564  0.004602331  2.189649

##存储每个类别的中心及频数

#标准化数据聚类结果

>centers_scale$freq<-as.data.frame(table(fit_kmeans_scale$cluster))[,2]

>centers_scale<-centers_scale[,c("freq","L","R","F","M","C")]

>write.csv(centers_scale,"centers_scale.csv",row.names = T)

对存储的数据在excel中作图分析


#归一化数据聚类结果

>centers_range$freq<-as.data.frame(table(fit_kmeans_range$cluster))[,2]

>centers_range<-centers_range[,c("freq","L","R","F","M","C")]

>write.csv(centers_range,"centers_range.csv",row.names = T)

对存储的数据在excel中作图分析:


说明:

通过两种数据预处理后的聚类分析结果对比,scale后的数据聚类在LRFMC5个变量上的分布更加明显,而range后的数据聚类结果主要差别集中在L和R上,所以分辨的效果不太好,所以采用scale预处理效果比较好。

#如果需要对客户贴上聚类类别标签,则将分类标签组合到包含客户会员号的数据中

>airdatanew$cluster<-as.data.frame(fit_kmeans_scale$cluster)

##聚类结果解读和应用

L和R越大,表示时间越长。L短表示新客户,意味着要激励,长意味着要挽留,在优劣势分析时,将L越长的设置为优势。

C越大,表示折扣越低,那么暗示客户对价格不敏感

M和F越大,表示客户乘机需求越大。

类别5的乘机需求高,折扣率排第二,其价值比较高,属于重要保持客户

类别2的乘机需求较低,但是其折扣率最高,表明其对价格不敏感,而且这部分客户量最小,属于重要发展客户。后期需要进一步刺激其需求,采取差异化策略。

类别3的乘机需求相对较高,但是其入会时间最长,因而属于重要的挽留客户。

类别4的乘机需求低,且最近乘机间隔时间最久,很有可能流失,因而属于低价值客户。

类别1的客户量最多,其乘机需求一般,但是乘机间隔较短,且入会时间最短,属于一般客户。




微信回复关键字即可学习

回复 R              R语言快速入门免费视频 
回复 统计          统计方法及其在R中的实现
回复 用户画像   民生银行客户画像搭建与应用 
回复 大数据      大数据系列免费视频教程
回复 可视化      利用R语言做数据可视化
回复 数据挖掘   数据挖掘算法原理解释与应用
回复 机器学习   R&Python机器学习入门 





您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存