【數據分析實戰經驗】航空公司客戶價值分析 LRMFC 模型(K-means聚類,工具python)


簡單介紹

聚類算法屬於無監督學習的一種,而其中KMeans算法是比較常用的聚類算法。

主要思想是: 1、在給定K值和K個初始類簇中心點的情況下,把每個點(亦即數據記錄)分到離其最近的類簇中心點所代表的類簇中。 2、 所有點分配完畢之后,根據一個類簇內的所有點重新計算該類簇的中心點(取平均值)。 3、再迭代的進行分配點和更新類簇中心點的步驟,直至類簇中心點的變化很小,或者達到指定的迭代次數。

本文數據量:62988, 共有44個客戶屬性,其中包含了會員卡號、入會時間、性別、年齡、會員卡級別、在觀測窗口內的飛行公里數、飛行時間等

第一步:數據探索

拿到數據集,先進行整體上的觀察

    import pandas as pd
  import numpy as np
  df = pd.read_csv( 'air_data.csv', encoding = 'utf-8') #讀取原始數據,指定UTF-8編碼(需要用文本編輯器將數據裝換為UTF-8編碼)
  print(df.shape)
  print(df.info)

在這里插入圖片描述 看看前5行

    df.head()

在這里插入圖片描述 簡單加工一下44屬性名稱 在這里插入圖片描述 進行空值,最小,最大值的計算

    ex = df.describe(percentiles = [], include = 'all').T #包括對數據的基本描述,percentiles參數是指定計算多少的分位數表(如1/4分位數、中位數等);T是轉置,轉置后更方便查閱
  ex['null'] = len(df)- ex['count'] #describe()函數自動計算非空值數,需要手動計算空值數
  ex = ex[['null', 'max', 'min']]
  ex.columns = [u'空值數', u'最大值', u'最小值'] #表頭重命名
  ex

在這里插入圖片描述 發現數據集存在票價為空,總飛行公里數大於0的臟數據

具體處理方法如下: 刪去票價為0的數據 及票價為0,折扣率不為0,總飛行公里數大於0的記錄

第二步:數據清洗

    df= df[df['SUM_YR_1'].notnull()&df['SUM_YR_2'].notnull()] #票價非空值才保留
   
  #只保留票價非零的,或者平均折扣率與總飛行公里數同時為0的記錄。
  index1 = df['SUM_YR_1'] != 0
  index2 = df['SUM_YR_2'] != 0
  index3 = (df['SEG_KM_SUM'] == 0) & (df['avg_discount'] == 0) #該規則是刪去臟數據,要么有飛有折扣有公里數,要么就都是折扣為0且里程數為0
  df= df[index1 | index2 | index3] #該規則是“或”
  df.T

在這里插入圖片描述 在這里插入圖片描述 最終得到62044樣本量

第三步 數據規約

在客戶分類中,RFM模型是一個經典的分類模型,——最近消費(Recency)、消費頻率(Frequency)、消費金額(Monetary)細分客戶群體,從而分析不同群體的客戶價值。

同樣金額的不同旅客對公司的價值是不同的,比如買長航線低等級艙位的旅客與短途高等級艙位旅客相比,后者相對價值更高。因此,M消費金額不能用於衡量客戶價值的一個因素,我們將其分解成兩個。一定時間內的飛行里程M,一定時間內所坐艙位的平均折扣系數C。

最終我們選擇: L(客戶入會時間距今月數)、 R(客戶最近一次乘機時間距今月數)、 F(客戶在樣本時間內乘機次數)、 M(客戶在樣本時間內的飛行里程)、 C(客戶在樣本時間內乘坐艙位的平均折扣系數) 因此,我們選擇入會時間(FFP_date)、樣本觀測結束時間LOAD TIME、飛行次數(flight count)、平均折扣率(AVG DISCOUNT)、總飛行公里數(seg-km-sum)、最后一次乘機時間距今時長(last to end)這6個屬性進行分析,刪去其他弱相關屬性

第四步 數據轉換–LRMFC

L=LOAD_TIME-FFP_DATE(入會時長)

R=LAST_TO_END(最近一次乘機時間)

F=FLIGHT_COUNT(頻次)

M=SEG_KM_SUM(飛行公里數)

C=AVG_DISCOUNT(平均折扣率)

    df['LOAD_TIME']=pd.to_datetime(df['LOAD_TIME']) #將字符串格式轉換為日期格式
  df['FFP_DATE'] = pd.to_datetime(df['FFP_DATE'])
  df['L']=df['LOAD_TIME']- df['FFP_DATE']
  #特征提取,只選L,LAST_TO_END,SEG_KM_SUM,avg_discount
  #即入會時間離觀測結束的天數,最近一次乘機的月數,觀測窗口的飛行次數,總飛行里程,折扣平均
   
  df1 = df[['L','LAST_TO_END','SEG_KM_SUM','FLIGHT_COUNT','avg_discount']]
   
  df1=df1.rename(
      columns = {'L':'L入會時間','LAST_TO_END':'R最近消費距今時間','SEG_KM_SUM':'M總里程','FLIGHT_COUNT':'F飛行次數','avg_discount':'C平均折扣率'},
      inplace = False
  )
  df1.head()

在這里插入圖片描述 觀察一下各組數據間的最大最小值 在這里插入圖片描述 由於不同的屬性相差范圍較大,這里進行標准化處理

    ##數據標准化
  df1 = (df1 - df1.mean(axis = 0))/(df1.std(axis = 0)) #簡潔的語句實現了標准化變換,類似地可以實現任何想要的變換。
  df1.columns=['Z'+i for i in df1.columns] #表頭重命名。
  df1.head()

在這里插入圖片描述

第五步 模型構建

首先采用無監督學習中K-means 進行模型構建,首先根據上述5個客戶指標進行聚類,其次根據結果結合業務針對不同客戶群進行分析,並進行排名。

K-Means算法主要就在於k=n_cluster參數的確定上面,到底是將k確定為幾能進行更好的分類.因為是無監督的聚類分析問題,所以不存在絕對正確的值,需要進行研究試探。

這里采用計算SSE(肘點)的方法,嘗試找到最好的K數值。

SSE值代表了每一個數據點離聚類中心的距離的評分,即為誤差平方。當k小於真實聚類數時,隨着k增大數據之間的聚合度會增加,SSE下降幅度會很大,當k快達到真實聚類值時,SSE下降幅度會變平穩,就想一個手肘的形狀,肘點即為最優k值。

注:剛學完吳恩達機器學習,其實有時候K值也要參考實際商業價值來決定,例如賣T恤,是只賣3種型號,S、M、L還是xs,s,m,l,xl,等,哪種更符合人群,影響后續銷量,這些都不一定是靠肘點能得到的,這點要注意。

代碼如下

    ##模型構建
  from sklearn.cluster import KMeans #導入K均值聚類算法
  import matplotlib.pyplot as plt
  SSE = []
  for k in range(1,9):
      estimator = KMeans(n_clusters=k)
      estimator.fit(df1)
      SSE.append(estimator.inertia_)#樣本到最近的聚類中心的距離平方之和
  X = range(1,9)
  plt.xlabel('k')
  plt.ylabel('SSE')
  plt.plot(X,SSE,'o-')
  plt.show()

在這里插入圖片描述 觀察圖像,並沒有的所謂的“肘”點出現,基本上是隨k值的增大逐漸減小的。在k=4,5這段區間變化放緩 設K=5

    #取k=5進行的類別聚類
  k = 5                      
  #df1中讀取數據並進行聚類分析
  #調用k-means算法#
  kmodel = KMeans(n_clusters = k, n_jobs = 4) #n_jobs是並行數,一般等於CPU數較好
  kmodel.fit(df1) #訓練模型
   
  kmodel.cluster_centers_ #查看聚類中心
  kmodel.labels_ #查看各樣本對應的類別
    r1 = pd.Series(kmodel.labels_).value_counts() #統計各個類別的數目
    r2 = pd.DataFrame(kmodel.cluster_centers_)#找出聚類中心
    # 所有簇中心坐標值中最大值和最小值
    max = r2.values.max()
    min = r2.values.min()
    r = pd.concat([r2, r1], axis = 1) #橫向連接(0是縱向),得到聚類中心對應的類別下的數目
    r.columns = list(df1.columns) + [u'各類別人數'] #重命名表頭
    r

在這里插入圖片描述

第六步 繪制可視化雷達圖

注:此部分代碼主要參考 傳送門

    ##繪圖
    ## 中文和負號的正常顯示
    plt.rcParams['font.sans-serif'] = 'SimHei'
    plt.rcParams['font.size'] = 12.0
    plt.rcParams['axes.unicode_minus'] = False
    fig=plt.figure(figsize=(10, 8))
    
    ax = fig.add_subplot(111, polar=True)
    center_num = r.values
    feature = ["L入會時間", "R最近消費距今時間", "M總里程", "F飛行次數程", "C平均折扣率"]
    N =len(feature)
    for i, v in enumerate(center_num):
        # 設置雷達圖的角度,用於平分切開一個圓面
        angles=np.linspace(0, 2*np.pi, N, endpoint=False)
        # 為了使雷達圖一圈封閉起來,需要下面的步驟
        center = np.concatenate((v[:-1],[v[0]]))
        angles=np.concatenate((angles,[angles[0]]))
        # 繪制折線圖
        ax.plot(angles, center, 'o-', linewidth=2, label = "第%d簇人群,%d人"% (i+1,v[-1]))
        # 填充顏色
        ax.fill(angles, center, alpha=0.25)
        # 添加每個特征的標簽
        ax.set_thetagrids(angles * 180/np.pi, feature, fontsize=15)
        # 設置雷達圖的范圍
        ax.set_ylim(min-0.1, max+0.1)
        # 添加標題
        plt.title('客戶群特征分析圖', fontsize=20)
        # 添加網格線
        ax.grid(True)
        # 設置圖例
        plt.legend(loc='upper right', bbox_to_anchor=(1.3,1.0),ncol=1,fancybox=True,shadow=True)
        
    # 顯示圖形
    plt.show()
    

在這里插入圖片描述

第七步 總結分析

基於LRFMC模型的具體含義,我們可以對這5個客戶群進行價值排名。同時,將這5個客戶群重新定義為五個等級的客戶類別:重要保持客戶,重要挽留客戶,重要發展客戶,一般發展客戶,低價值客戶。 注意:每次跑出來的類型順序會不一樣,要做好辨別。

對應客戶群1: 重要保持客戶:這類客戶乘坐的次數(F)和飛行的里程數(M)都很高。折扣率(C)和入會時間(L)也不低,說明他們經常乘坐飛機,且有一定經濟實力,是航空公司的高價值客戶。

對應客戶群2 最大的特點是時間間隔差值(R)最大,其他指標表現一般,分析可能是“季節型客戶”,一年中可能有一段時間需要乘坐飛機進行旅行等等,屬於一般發展客戶

對應客戶群3 重要挽留客戶:這類客戶最大的特點就是入會的時間(L)較長,入會時間長(L),平均折扣率較低,而且總里程和總次數都不高,分析可能是流失的客戶,需要在爭取一下,盡量讓他們“回心轉意”;

對應客戶群4: 重要發展客戶:這類客戶平均折扣率很高(C),最近乘坐過本航班時間間隔(R)短,但是乘坐的次數(F)和(M)都很低,成為會員的時間也很近(L),說明這些乘客剛入會員不久,所以乘坐飛機次數少,是未來重要發展客戶。

對應客戶群5

低價值客戶:這類客戶乘坐時間間隔長(R)或乘坐次數(F)和總里程(M)低,平均折扣也很低,各方面的數據都是比較低的

最終將表格的客戶進行分類

    df1['聚類類別'] = kmodel.labels_
    #划分客戶類別
    for i in range(len(df1)):
        if df1['聚類類別'][i] == 0:
            df1['聚類類別'][i] = '重要保持客戶'
    
        elif df1['聚類類別'][i] == 1:
            df1['聚類類別'][i] = '一般發展客戶'
    
        elif df1['聚類類別'][i] == 2:
            df1['聚類類別'][i] = '重要挽留客戶'
    
        elif df1['聚類類別'][i] == 3:
            df1['聚類類別'][i] = '重要發展客戶'
        else:
            df1['聚類類別'][i] = '低價值客戶'
    
    #重命名屬性
        df1.columns = ['L','R','M','F','C','客戶類別']

結果如下 在這里插入圖片描述

參考文章: 1 2 3

保持渴求,不要沉寂

在這里插入圖片描述

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM