利用Python分析航空公司客戶價值

                                                                    利用Python分析航空公司客戶價值

一、背景介紹

       隨着社會生活中數據量的急劇增多,如何從這些海量的數據中提取與發掘出對我們決策有用的信息成爲當前亟待解決的題,因此,數據分析與挖掘技術在這些年得到了廣泛的發展,也受到了足夠的重視。面對不同領域的數據,不同的任務目標,我們在進行數據分析時也會選擇不同的模型來進行建模,從而發現數據中的特徵,提取其中的價值。常見的數據挖掘模型有:分類與預測、聚類分析、關聯規則、時序模式、離羣點檢測等。這些模型,在我們的生活中已經有了廣泛的應用。例如航空公司的客戶價值分析,就是對用戶數據進行聚類分析,發掘出不同價值羣的用戶,然後有針對性的制定相應的營銷手段,實現精準化運營,以期獲取最大的用戶轉化率。
       本篇博文的實例來源於《Python數據分析與挖掘實踐》(第二版)中的第七章。實現的主要目標是:
       1,藉助航空公司客戶數據,對客戶進行分類。
       2,對不同客戶類別進行特徵分析,比較不同類別的客戶價值。
       3,針對不同價值的客戶類別制定相應的營銷策略,爲其提供個性化服務。

二、分析步驟與流程

       此案例的總體流程圖如下所示。簡單來說就是:因爲最開始只是要構建模型,所以不需要使用航空公司的全部客戶數據,只需要先從業務系統中抽取某一時段的客戶數據作爲訓練即可,然後對數據從宏觀上進行分析,之後對數據進行處理,使之能夠達到建模的要求,最後選擇合適的聚類算法建模並且對結果進行反饋。

       2.1. 建模數據的獲取:

        這個可以從公司的業務系統選擇性抽取,例如抽取最近兩年的數據。數據的屬性說明如下圖所示:

       2.2. 數據的宏觀性探索分析:

       2.2.1 描述性統計分析 - 查看屬性字段的缺失值、平均值、最大值、最小值等情況,從宏觀層面上了解數據。

import pandas as pd

datafile = r'C:\Users\itour\Desktop\air_customer_data.csv'
data = pd.read_csv(datafile, encoding='utf-8')

explore = data.describe(percentiles=[], include='all').T  # 使用統計函數對數據進行統計分析
explore['null'] = len(data) - explore['count']  # 計算空值數
# describe有很多統計子項,這裏就取我們要用到的即可
explore = explore[['null', 'mean', 'max', 'min']]
explore.columns = ['空值記錄數', '最大值', '最小值', '平均值']

print(explore)

       通過上圖可以看出有一些記錄含有空值,這樣的數據對建模可能會有影響,因此,在後面的數據預處理環節,要把這些空值刪掉。

       2.2.2 數據的分佈分析 - 尋找客戶信息的分佈規律,例如入會時間分佈、年齡分佈、性別分佈、會員等級分佈等等。

       1)入會時間分佈圖展示

import pandas as pd
from datetime import datetime
import matplotlib.pyplot as plt

datafile = r'C:\Users\itour\Desktop\air_customer_data.csv'
data = pd.read_csv(datafile, encoding='utf-8')

ffp = data['FFP_DATE'].apply(lambda x: datetime.strptime(x, '%Y/%m/%d'))
ffp_year = ffp.map(lambda x: x.year)

plt.rcParams['font.sans-serif'] = 'SimHei'
plt.rcParams['axes.unicode_minus'] = False
# 繪製各年份會員入會人數直方圖
plt.hist(ffp_year, bins='auto', color='green')
plt.xlabel('年份')
plt.ylabel('入會人數')
plt.title('各年份會員入會人數')

plt.show()

     2)會員性別比例分佈圖

import matplotlib.pyplot as plt

datafile = r'C:\Users\itour\Desktop\air_customer_data.csv'
data = pd.read_csv(datafile, encoding='utf-8')

# 獲取會員中不同的性別人數
male = pd.value_counts(data['GENDER'])['男']
female = pd.value_counts(data['GENDER'])['女']

# 繪製會員分佈餅狀圖
plt.rcParams['font.sans-serif'] = 'SimHei'
plt.rcParams['axes.unicode_minus'] = False

plt.pie([male, female], labels=['男', '女'], colors=['lightskyblue', 'green'], autopct='%1.1f%%')
plt.title('會員性別比例')
plt.show()

    3)會員年齡分佈箱型圖

import pandas as pd
from datetime import datetime
import matplotlib.pyplot as plt

datafile = r'C:\Users\itour\Desktop\air_customer_data.csv'
data = pd.read_csv(datafile, encoding='utf-8')

# 提取會員的年齡
age = data['AGE'].dropna()
age = age.astype('int64')

# 繪製會員年齡分佈箱型圖
plt.rcParams['font.sans-serif'] = 'SimHei'
plt.rcParams['axes.unicode_minus'] = False

plt.boxplot(age, patch_artist=True, labels=['會員年齡'], boxprops={'facecolor': 'lightblue'})
plt.title('會員年齡分佈箱型圖')
plt.grid(axis='y')
plt.show()

       2.2.3 數據屬性之間的相關性分析 - 這對特徵的選擇來說非常有用,通過分析屬性之間的關聯性,可以確定選擇哪些屬性作爲特徵值,哪些則是可以忽略的。

import pandas as pd
from datetime import datetime


datafile = r'C:\Users\itour\Desktop\air_customer_data.csv'
data = pd.read_csv(datafile, encoding='utf-8')

data_corr = data[['FFP_TIER', 'FLIGHT_COUNT', 'LAST_TO_END', 'SEG_KM_SUM', 'EXCHANGE_COUNT', 'Points_Sum']]
age_1 = data['AGE'].fillna(0)
data_corr['AGE'] = age_1.astype('int64')

ffp = data['FFP_DATE'].apply(lambda x: datetime.strptime(x, '%Y/%m/%d'))
ffp_year = ffp.map(lambda x: x.year)
data_corr['ffp_year'] = ffp_year

# 計算相關性矩陣
dt_corr = data_corr.corr(method='pearson')
print(dt_corr)

       從上面的圖可以看出,有些屬性的相關性較強,有些則較弱。例如 ffp_year與FFP_TIER的相關性就弱,已經是負相關了。而FLIGHT與FFP_TIER的相關性就稍微強一些。屬性之間的相關性關係,也是在做特徵降維的一個重要參考量,有時候特徵較多會嚴重增加建模的時間,爲了提高效率,需要對特徵進行降維,構建有代表性的特徵進行建模。

       2.3. 數據預處理:

       通過前面的宏觀分析我們也看到,有一些記錄是空值,還有一些值出現了明顯的錯誤,而且,在我們後面要構建的LRFMC模型中,這三個特徵並不能直接從屬性中抽取,而是要根據規則重新計算得到,因此,需要對這些從業務系統中抽取的數據做預處理,使之能夠適合建模的需要。數據預處理主要包括數據清洗、屬性規約、數據變換等步驟。

       2.3.1 數據清洗  - 刪除異常值

import pandas as pd
from datetime import datetime

datafile = r'C:\Users\itour\Desktop\air_customer_data.csv'

clean_datafile = r'C:\Users\itour\Desktop\air_customer_data_clean.csv'

data = pd.read_csv(datafile, encoding='utf-8')

print('原始數據的數據大小:', data.shape)

# 去除票價爲空的票價
airline_notnull = data.loc[data['SUM_YR_1'].notnull() & data['SUM_YR_2'].notnull(), :]
print(airline_notnull.shape)

# 只保留票價非0的,或者平均折扣率不爲0且總飛行公里數大於0的記錄
index1 = airline_notnull['SUM_YR_1'] != 0
index2 = airline_notnull['SUM_YR_2'] != 0
index3 = (airline_notnull['SEG_KM_SUM'] > 0) & (airline_notnull['avg_discount'] != 0)
index4 = airline_notnull['AGE'] > 0
clean_data = airline_notnull[(index1 | index2) & index3 & ~index4]
print(clean_data.shape)
# 保存清洗後的文件
clean_data.to_csv(clean_datafile)

       2.3.2 屬性規約 - 選取參與建模的屬性

       屬性規約的目的就是從衆多的屬性中選取需要參與建模的、能夠反應數據整體特徵的屬性,刪除不相關、弱相關、或者冗餘的屬性 ,從而提高建模效率。在屬性特徵選擇過程中,可以根據上面步驟的相關性分析,大致瞭解屬性的相關性,然後推導出參與建模的屬性。在客戶價值識別方面,應用最廣泛的模型就是RFM模型,其中,R(Recency)代表指的是最近一次消費時間與截止時間的間隔,F(Frequency)指客戶某段時間內所消費的次數,M(Monetary)指客戶在某段時間內所消費的金額。在RFM模型中,(R,F,M)是計算客戶價值的最重要的特徵。在航空公司客戶價值領域,常用的是LRFMC模型,需要在上述模型的基礎上再加兩個特徵,LRFMC模型的屬性意義如下圖:

      根據LRFMC模型,需要選擇的屬性有:FFP_DATE,LOAD_TIME,FLIGHT_COUNT,AVG_DISCOUNT,SEG_KM_SUM,LAST_TO_END。從數據集中選取需要的屬性,代碼如下:

import pandas as pd
from datetime import datetime

clean_datafile = r'C:\Users\itour\Desktop\air_customer_data_clean.csv'

guiyue_datafile = r'C:\Users\itour\Desktop\air_customer_data_guiyue.csv'

clean_data = pd.read_csv(clean_datafile, encoding='utf-8')

# 選取需要的屬性
air_selection = clean_data[['FFP_DATE', 'LOAD_TIME', 'LAST_TO_END', 'FLIGHT_COUNT', 'SEG_KM_SUM', 'avg_discount']]

print(air_selection.head())

# 保存規約後的數據
air_selection.to_csv(guiyue_datafile)

     2.3.2 數據變換 - 構建建模特徵值,進行數據標準化

       在LRFMC模型中,這其中的特徵值需要經過規約後的屬性通過變換得到,得到這些特徵值之後,往往還需要對數據集進行標準化處理,爲什麼要進行標準化呢?因爲不同屬性的值通常具有不同的計量單位和數量級。當各指標間的水平相差很大時,如果直接用原始指標值進行分析,就會突出數值較高的指標在綜合分析中的作用,相對削弱數值水平較低指標的作用。因此,爲了保證結果的可靠性,需要對原始指標數據進行標準化處理。做法通常有:將數據按比例縮放,使之落入一個小的特定區間。去除數據的單位限制,將其轉化爲無單位限制的純數值,便於不同單位或量級的指標能夠進行比較和加權處理。

      數據變換代碼如下:

import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler

guiyue_datafile = r'C:\Users\itour\Desktop\air_customer_data_guiyue.csv'
stand_datafile = r'C:\Users\itour\Desktop\air_customer_data_std.npz'

guiyue_data = pd.read_csv(guiyue_datafile, encoding='utf-8')

# 特徵構造,並將時間類型轉化爲int類型
L = pd.to_datetime(guiyue_data['LOAD_TIME']) - pd.to_datetime(guiyue_data['FFP_DATE'])
L = (L.astype('str').str.split().str[0]).astype('int') / 30

air_feature = pd.concat([L, guiyue_data.iloc[:, 3:]], axis=1)
print('構建的 LRFMC 模型屬性的前5個數據爲:\n', air_feature.head())

# 數據標準化
std_data = StandardScaler().fit_transform(air_feature)
np.savez(stand_datafile, std_data)

print('標準化後 LRFMC 的 前5個屬性數據爲:\n', std_data[:5, :])

      2.4. 模型構建:

        客戶的價值模型構建主要有兩個部分組成:第一部分,根據之前歸納出的5個特徵,對客戶進行聚類分羣;第二部分,對每個羣的客戶進行特徵分析,探索其中的客戶價值規律,並對各個客戶羣進行排名。

        2.4.1 聚類分羣

import pandas as pd
import numpy as np
from sklearn.cluster import KMeans

guiyue_datafile = r'C:\Users\itour\Desktop\air_customer_data_guiyue.csv'
stand_datafile = r'C:\Users\itour\Desktop\air_customer_data_std.npz'

# 讀取標準化之後的數據
std_data = np.load(stand_datafile)['arr_0']

k = 5  # 確定聚類中心數,這裏選擇5,也就是分爲5個羣。這個值的確定,是有一定的要求的,這裏不做描述

# 模型訓練
kmeans_model = KMeans(n_clusters=k, n_jobs=4, random_state=123)
fit_kmeans = kmeans_model.fit(std_data)

# 查看聚類結果
kmeans_cc = kmeans_model.cluster_centers_   # 聚類中心
print('各聚類中心爲: \n', kmeans_cc)

kmeans_label = kmeans_model.labels_   # 樣本的類別標籤

r = pd.Series(kmeans_label).value_counts()  # 統計不同類別樣本的數目
print('每個類別的數目爲:\n', r)

# 輸出聚類分羣的結果
cluster_center = pd.DataFrame(kmeans_cc, columns=['ZL', 'ZR', 'ZF', 'ZM', 'ZC'])

cluster_center['聚類個數'] = r

cluster_center.index = pd.DataFrame(kmeans_label).drop_duplicates().iloc[:, 0]

print('聚類結果如下表所示:\n', cluster_center)

     2.4.2 客戶價值分析

      針對聚類的結果進行特徵分析,繪製客戶分羣雷達圖,如下所示:

import pandas as pd
import numpy as np
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt

guiyue_datafile = r'C:\Users\itour\Desktop\air_customer_data_guiyue.csv'
stand_datafile = r'C:\Users\itour\Desktop\air_customer_data_std.npz'

# 讀取標準化之後的數據
std_data = np.load(stand_datafile)['arr_0']

k = 5  # 確定聚類中心數,這裏選擇5,也就是分爲5個羣。這個值的確定,是有一定的要求的,這裏不做描述

# 模型訓練
kmeans_model = KMeans(n_clusters=k, n_jobs=4, random_state=123)
fit_kmeans = kmeans_model.fit(std_data)

# 查看聚類結果
kmeans_cc = kmeans_model.cluster_centers_  # 聚類中心

kmeans_label = kmeans_model.labels_  # 樣本的類別標籤

# 輸出聚類分羣的結果
labels = ['ZL', 'ZR', 'ZF', 'ZM', 'ZC']

cluster_center = pd.DataFrame(kmeans_cc, columns=labels)

legen = ['客戶羣' + str(i + 1) for i in cluster_center.index]  # 客戶羣命名

lstype = ['-', '--', (0, (3, 5, 1, 5, 1, 5)), ':', '-.']

kinds = list(cluster_center.iloc[:, 0])

cluster_center = pd.concat([cluster_center, cluster_center[['ZL']]], axis=1)

centers = np.array(cluster_center.iloc[:, 0:])

# 分割圓周長,讓其閉合
n = len(labels)
angle = np.linspace(0, 2 * np.pi, n, endpoint=False)
angle = np.concatenate((angle, [angle[0]]))

# 繪製雷達圖
fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(111, polar=True)  # 以極座標的形式繪製圖形
# 處理中文顯示問題
plt.rcParams['font.sans-serif'] = 'SimHei'
plt.rcParams['axes.unicode_minus'] = False  # 正常顯示負號

# 畫線
for i in range(len(kinds)):
    ax.plot(angle, centers[i], linestyle=lstype[i], linewidth=2, label=kinds[i])
# 添加屬性標籤
ax.set_thetagrids(angle * 180 / np.pi, labels)

plt.title('客戶特徵分析雷達圖')
plt.legend(legen)
plt.show()

       通過分析各個客戶羣的雷達圖,可以看到不同類的客戶偏好還是有一些差別的,我們可以根據這些差別制定符合客戶羣的營銷手段和策略。

三、總結

       這篇博文的示例以航空公司客戶價值分析爲基礎,介紹了原始數據的宏觀性分析、數據預處理、數據建模的一整套流程,涉及了數據分析的主要過程。因此,還是非常有借鑑意義的。通過這個案例,可以很好的夠掌握建模過程中的基本方法,以及Python這種語言的基本用法。

完整代碼及數據集鏈接

發佈了62 篇原創文章 · 獲贊 171 · 訪問量 23萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章