航空公司客戶價值和流失分析

1 引言

最近終于把機器學習的算法部分整完了,可以再玩一個例子义屏。這次是抽取《R語言數據分析與挖掘實戰(zhàn)》里面一個航空公司客戶價值分析的例子靠汁。

前一部分在書中有代碼蜂大,可以直接一步一步敲上去闽铐。后面拓展部分,作品也只是留了個思路奶浦,我就順著思路做了下去兄墅,結果雖然有一定的準確度,但還是有點寒磣澳叉。還需要更加修正來提高精準度隙咸。學習還得繼續(xù)沐悦。

航空公司客戶價值分析

2 數據初探

給定了客戶的一些數據信息,為了對不同的客戶采取不同的營銷措施五督,通過建立合理的客戶價值評價模型藏否,來對客戶進行細分。對不同的客戶進行價值比較充包,并制定相應的營銷策略副签,從而對客戶提供有效的個性化服務。

# 設置工作空間
setwd("/Users/zhangyi/Desktop/clientanalyze/data/")
# 數據讀取
datafile <- read.csv('air_data.csv', header = TRUE)
head(datafile)
初始數據
# 確定要探索分析的變量
col <- c(15:18, 20:29)  # 去掉日期型變量
# 輸出變量最值基矮、缺失情況
summary(datafile[, col])

這個案例選擇的是客戶的入會時長L淆储、消費時間間隔R、消費頻率F家浇、飛行里程M和折扣系數的平均值C五個指標作為航空公司識別客戶價值指標本砰。

傳統(tǒng)的RFM模型太少,而細分太多的話钢悲,營銷成本也會相應提高点额。當然,這不是這個案例的重點哈莺琳。

# 丟棄票價為空的記錄
delet_na <- datafile[-which(is.na(datafile$SUM_YR_1) |
                             is.na(datafile$SUM_YR_2)), ]

# 丟棄票價為0咖楣、平均折扣率不為0、總飛行公里數大于0的記錄
index <- ((delet_na$SUM_YR_1 == 0 & delet_na$SUM_YR_2 == 0)
          * (delet_na$avg_discount != 0)
          * (delet_na$SEG_KM_SUM > 0))
deletdata <- delet_na[-which(index == 1), ]

# 保存清洗后的數據
cleanedfile <- deletdata

# 構造L芦昔、R诱贿、F、M咕缎、C指標
# 轉換為時間格式
cleanedfile$FFP_DATE <- as.Date(cleanedfile$FFP_DATE)
cleanedfile$LOAD_TIME <- as.Date(cleanedfile$LOAD_TIME)

# 構造時間間隔格式
library(lubridate)  # 處理日期格式數據包
interval <- interval(cleanedfile$FFP_DATE, cleanedfile$LOAD_TIME)  

# 以月為單位計算時長珠十,輸入為時間間隔
L <- time_length(interval, 'month')
L <- round(L, 2)
R <- cleanedfile$LAST_TO_END
F <- cleanedfile$FLIGHT_COUNT
M <- cleanedfile$SEG_KM_SUM
C <- cleanedfile$avg_discount

# 數據整合
airdata <- data.frame(L, R, F, M, C)
write.csv(airdata, 'zscoredata.csv', row.names = FALSE)
LRFMC指標

但由于各個指標之間的取值范圍差異較大,于是采取標準化處理來消除數量級的影響凭豪。

# 數據讀取
datafile <- read.csv('zscoredata.csv', header = TRUE)

# 數據標準化
zscoredfile <- scale(datafile)
colnames(zscoredfile)=c("ZL","ZR","ZF","ZM","ZC")
# 數據寫出
write.csv(zscoredfile, 'zscoreddata.csv')
標準化后的LRFMC

3 聚類分析

現在就可以對其進行聚類分析了焙蹭,當然,在聚類分析的同時嫂伞,要結合業(yè)務的理解孔厉。

inputfile <- read.csv('zscoreddata.csv', header = TRUE)
# 聚類分析
result <- kmeans(inputfile, 5)

# 結果輸出
type <- result$cluster
table(type)  # 查看類別分布
centervec <- result$center

由于K-Means是隨機選擇類標號,每次的結果可能有所不同帖努。

# 各簇中心的條形圖

library(reshape)
library(ggplot2)
# 條形圖
# 將數據格式轉換為畫圖所需要的格式
data.bar <- as.data.frame(t(result$center))
colnames(data.bar) <- paste("class", 1:5, sep = "")
data.bar <- data.frame(index = c("L", "R", "F", "M", "C"), data.bar[2:6,])
data.bar <- melt(data.bar, c("index"))
colnames(data.bar) <- c("index", "class", "center")
head(data.bar)
ggplot(data.bar, aes(x = index, y = center, fill = class)) + 
  scale_y_continuous(limits = c(-1, 3)) + geom_bar(stat = "identity") + 
  facet_grid(class ~ .) + guides(fill = FALSE) + theme_bw()
類別條形圖
# 每一簇各指標的關系程度  --雷達圖
# install.packages("fmsb")
library(fmsb)
max <- apply(result$centers[,2:6], 2, max)
min <- apply(result$centers[,2:6], 2, min)
data.radar <- data.frame(rbind(max, min, result$centers[,2:6]))
radarchart(data.radar, pty = 32, plty = 1, plwd = 2, vlcex = 0.7)
# 給雷達圖加圖例
L <- 1.2
for(i in 1:5){
  text(1.8, L, labels = paste("--class", i), col = i)
  L <- L - 0.2
}
雷達圖

通過雷達圖和條形圖撰豺,我們可以簡單分析出整個客戶在分成五種之后,五種客戶類型在LRFMZ各個屬性上的特點就可以分辨清楚了拼余。(至于各個屬性結合起來代表的客戶類型需要根據業(yè)務進行判斷污桦,感興趣的看書咯)

# 查看各簇個數占比 --餅圖
# install.packages("plotrix")
library(plotrix)
data.pie <- c(result$size)
prob <- paste(round(result$size / sum(result$size) * 100, 2), "%", sep = "")
lbls <- c(paste("class", 1:5, sep = "", ": ", prob))
pie3D(data.pie, labels = lbls, labelcex = 0.8, explode = 0.1,
      col = c("lightskyblue", "lightcyan", "turquoise",
                "lightskyblue3", "steelblue"))
      labels <- c("London", "New York", "Singapore", "Mumbai")

餅圖

在客戶類型分辨好之后,就可以根據客戶的特點制定不同策論的營銷策略匙监。同時凡橱,每隔半年要對模型進行重新訓練小作,以保持其穩(wěn)定性。

4 構建模型

前面主要對客戶的價值進行了分析稼钩,在后面會對客戶的流失進行分析顾稀。通過對新老客戶進行分類(飛行次數大于6次為老客戶),客戶類型定義(流失客戶的定義為第二年的飛行次數與第一年飛行次數比例小于50%坝撑,準流失在[50,90)础拨,未流失為大于90%)。

同時绍载,選取部分關鍵屬性(會員卡級別诡宗、客戶類型等),隨機選取80%數據作為訓練樣本击儡,剩余20%作為測試樣本建立流失模型塔沃,預測未來客戶的類別歸屬。

### 拓展
datafile <- read.csv('拓展思考樣本數據.csv', header = TRUE)
# 確定要探索分析的變量
col <- c(15:18, 20:29)  # 去掉日期型變量
# 輸出變量最值阳谍、缺失情況
summary(datafile[, col])
# 丟棄票價為空的記錄
delet_na <- datafile[-which(is.na(datafile$SUM_YR_1) |
                             is.na(datafile$SUM_YR_2)), ]

# 丟棄票價為0蛀柴、平均折扣率不為0、總飛行公里數大于0的記錄
index <- ((delet_na$SUM_YR_1 == 0 & delet_na$SUM_YR_2 == 0)
          * (delet_na$avg_discount != 0)
          * (delet_na$SEG_KM_SUM > 0))
deletdata <- delet_na[-which(index == 1), ]

# 保存清洗后的數據
cleanedfile <- deletdata

T指標為客戶類型(流失矫夯、準流失和未流失)鸽疾,F指標為老客戶和新客戶,R為會員卡級別训貌,I為平均乘機時間間隔制肮,D為平均這折扣率

# 構造T(lost-1,lossing0,stay1)、R(FFP_TIER)递沪、F豺鼻、I、D指標
# 轉換為時間格式
cleanedfile$FFP_DATE <- as.Date(cleanedfile$FFP_DATE)
cleanedfile$LOAD_TIME <- as.Date(cleanedfile$LOAD_TIME)

# 構造時間間隔格式
library(lubridate)  # 處理日期格式數據包
interval <- interval(cleanedfile$FFP_DATE, cleanedfile$LOAD_TIME)  

# 以月為單位計算時長款慨,輸入為時間間隔
L <- time_length(interval, 'month')
L <- round(L, 2)
R <- cleanedfile$FFP_TIER
I <- cleanedfile$AVG_INTERVAL
D <- cleanedfile$avg_discount

F <- c() # 老客戶儒飒、新客戶
for (i in 1: nrow(cleanedfile)){
    if (cleanedfile$FLIGHT_COUNT[i]>6){
    F[i] <- 1
    }
    else F[i] <- 0 
}       
        
T <- c()
T.rate <- cleanedfile$L1Y_Flight_Count/cleanedfile$P1Y_Flight_Count
for (i in 1: nrow(cleanedfile)){
    if (T.rate[i] >= 0.9){
    T[i] <- 1
    }
    if (T.rate[i] < 0.9 & T.rate[i] >= 0.5){
    T[i] <- 0}
    else T[i] <- -1 
}
# 數據整合
extscoredata<- data.frame(R, I, D, F, T)
write.csv(extscoredata, 'extscoredata.csv', row.names = FALSE)
# 數據標準化
extscoredata<- scale(extscoredata)
colnames(extscoredata)=c("ZR","ZI","ZD","ZF","ZT")
# 數據寫出
write.csv(extscoredata, 'extscoreddata.csv')


# 數據劃分
# 把數據分為兩部分:訓練數據、測試數據
# 讀入數據
Data <- read.csv("extscoreddata.csv")
# 數據分割
set.seed(1234)  # 設置隨機種子
# 定義序列ind檩奠,隨機抽取1和2,1的個數占80%桩了,2的個數占20%
ind <- sample(2, nrow(Data), replace = TRUE, prob = c(0.8, 0.2))
trainData <- Data[ind == 1,]  # 訓練數據
testData <- Data[ind == 2,]  # 測試數據
# 數據存儲
write.csv(trainData, "trainData.csv", row.names = FALSE)
write.csv(testData, "testData.csv", row.names = FALSE)

劃分好數據,建立神經網絡模型埠戳,將客戶類型轉化為因子井誉。

# 神經網絡模型構建
# 讀取數據
trainData <- read.csv("trainData.csv")

# 將class列轉換為factor類型
trainData <- transform(trainData, class = as.factor(ZT))



# 神經網絡模型構建
library(nnet) # 加載nnet包
# 利用nnet建立神經網絡
nnet.model <- nnet(ZT~ ZR + ZI+ ZD+ ZF, trainData, 
                   size = 10, decay = 1)
summary(nnet.model)

# 建立混淆矩陣
confusion <- table(trainData$ZT, predict(nnet.model, trainData, 
                                            ))
accuracy <- sum(diag(confusion)) * 10000 / sum(confusion)

# 保存輸出結果
output_nnet.trainData <- cbind(trainData, predict(nnet.model, trainData))
colnames(output_nnet.trainData) <- c(colnames(trainData), "OUTPUT")
write.csv(output_nnet.trainData, "output_nnet.trainData.csv", 
          row.names = FALSE)

5 檢驗驗證

通過ROC曲線來檢驗模型是否準確。

# 保存神經網絡模型
save(nnet.model, file = "nnet.model.RData")

# ROC曲線
# 設置工作空間
# 讀取數據
testData <- read.csv("testData.csv")
# 讀取模型
load("nnet.model.RData")

# ROC曲線
library(ROCR)  # 加載ROCR包
# 畫出神經網絡模型的ROC曲線
nnet.pred <- prediction(predict(nnet.model, testData), testData$ZT)
nnet.perf <- performance(nnet.pred, "tpr", "fpr") 
plot(nnet.perf)
ROC

ROC曲線真心有不準乞而,麻煩就在于送悔,我已經嘗試了調整算法里的各種參數,結果也基本沒怎么變化爪模。所以欠啤,最近看了寒小陽的博客,打算再試試模型融合深入挖掘一下屋灌。

6 問題與總結:

殘留的問題在于:

  • 如何設計更好的算法洁段,讓模型的精準度更高
  • 在算法特定的前提下,如何設計選取特征量共郭,使模型更準確

也已經請教了迷途和vivian桑:

一把特征工程做好哗戈,選的predictor好能提高征冷,很多predictor correlated的話有時候不好;
二把數據transformation做好,比如中心化啊~標準化啊瞎嬉,log一下你的predictor;
三加入一些interaction或者predictor的平方可以抓一些high order moment的信息莹弊;
四一般非線性關系多的時候可以試試決策樹隨機森林神經網絡等等~

“針對同一批數據毕匀,改善預測準確性的方法,有幾種年缎,進去模型的數據悔捶,不同算法,算法的不同參數单芜。以往的經驗蜕该,效果比較明顯的是盡量折騰進入模型的數據。對數據的處理層面洲鸠,單一指標可以衍生n多指標堂淡,比如環(huán)比,同比扒腕,占比等等淤齐。數據量綱不同引起的問題,數據標準化(歸一化)都是要嘗試處理的”

哎袜匿,路途遙遠更啄,繼續(xù)努力。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末居灯,一起剝皮案震驚了整個濱河市祭务,隨后出現的幾起案子,更是在濱河造成了極大的恐慌怪嫌,老刑警劉巖义锥,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異岩灭,居然都是意外死亡拌倍,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來柱恤,“玉大人数初,你說我怎么就攤上這事」K常” “怎么了泡孩?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長寺谤。 經常有香客問我仑鸥,道長,這世上最難降的妖魔是什么变屁? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任眼俊,我火速辦了婚禮,結果婚禮上粟关,老公的妹妹穿的比我還像新娘疮胖。我一直安慰自己,他們只是感情好誊役,可當我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布获列。 她就那樣靜靜地躺著,像睡著了一般蛔垢。 火紅的嫁衣襯著肌膚如雪击孩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天鹏漆,我揣著相機與錄音巩梢,去河邊找鬼。 笑死艺玲,一個胖子當著我的面吹牛括蝠,可吹牛的內容都是我干的。 我是一名探鬼主播饭聚,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼忌警,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了秒梳?” 一聲冷哼從身側響起法绵,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎酪碘,沒想到半個月后朋譬,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡兴垦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年徙赢,在試婚紗的時候發(fā)現自己被綠了字柠。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡狡赐,死狀恐怖窑业,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情阴汇,我是刑警寧澤数冬,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布节槐,位于F島的核電站搀庶,受9級特大地震影響,放射性物質發(fā)生泄漏铜异。R本人自食惡果不足惜哥倔,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望揍庄。 院中可真熱鬧咆蒿,春花似錦、人聲如沸蚂子。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽食茎。三九已至蒂破,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間别渔,已是汗流浹背附迷。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留哎媚,地道東北人喇伯。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像拨与,于是被迫代替她去往敵國和親稻据。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,927評論 2 355

推薦閱讀更多精彩內容