背景和目标
行业内竞争
民航的竞争除了三大航空公司之间的竞争之外,还将加入新崛起的各类小型航空公司、民营航空公司,甚至国外航空巨头。航空产品生产过剩,产品同质化特征愈加明显,于是航空公司从价格、服务间的竞争逐渐转向对客户的竞争。
行业外竞争
随着高铁、动车等铁路运输的兴建,航空公司受到巨大冲击。
目标
借助航空公司客户数据,对客户进行分类。
对不同的客户类别进行特征分析,比较不同类别客户的客户价值。
对不同价值的客户类别提供个性化服务,制定相应的营销策略。
数据集下载
读取数据
1
| data = pd.read_csv('air_data.csv', encoding='gb18030')
|
|
MEMBER_NO |
FFP_DATE |
FIRST_FLIGHT_DATE |
GENDER |
FFP_TIER |
WORK_CITY |
WORK_PROVINCE |
WORK_COUNTRY |
AGE |
LOAD_TIME |
... |
ADD_Point_SUM |
Eli_Add_Point_Sum |
L1Y_ELi_Add_Points |
Points_Sum |
L1Y_Points_Sum |
Ration_L1Y_Flight_Count |
Ration_P1Y_Flight_Count |
Ration_P1Y_BPS |
Ration_L1Y_BPS |
Point_NotFlight |
0 |
54993 |
2006/11/2 |
2008/12/24 |
男 |
6 |
. |
北京 |
CN |
31.0 |
2014/3/31 |
... |
39992 |
114452 |
111100 |
619760 |
370211 |
0.509524 |
0.490476 |
0.487221 |
0.512777 |
50 |
1 |
28065 |
2007/2/19 |
2007/8/3 |
男 |
6 |
NaN |
北京 |
CN |
42.0 |
2014/3/31 |
... |
12000 |
53288 |
53288 |
415768 |
238410 |
0.514286 |
0.485714 |
0.489289 |
0.510708 |
33 |
2 |
55106 |
2007/2/1 |
2007/8/30 |
男 |
6 |
. |
北京 |
CN |
40.0 |
2014/3/31 |
... |
15491 |
55202 |
51711 |
406361 |
233798 |
0.518519 |
0.481481 |
0.481467 |
0.518530 |
26 |
3 |
21189 |
2008/8/22 |
2008/8/23 |
男 |
5 |
Los Angeles |
CA |
US |
64.0 |
2014/3/31 |
... |
0 |
34890 |
34890 |
372204 |
186100 |
0.434783 |
0.565217 |
0.551722 |
0.448275 |
12 |
4 |
39546 |
2009/4/10 |
2009/4/15 |
男 |
6 |
贵阳 |
贵州 |
CN |
48.0 |
2014/3/31 |
... |
22704 |
64969 |
64969 |
338813 |
210365 |
0.532895 |
0.467105 |
0.469054 |
0.530943 |
39 |
5 rows × 44 columns
数据探索
查看数据的摘要信息
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 62988 entries, 0 to 62987
Data columns (total 44 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 MEMBER_NO 62988 non-null int64
1 FFP_DATE 62988 non-null object
2 FIRST_FLIGHT_DATE 62988 non-null object
3 GENDER 62985 non-null object
4 FFP_TIER 62988 non-null int64
5 WORK_CITY 60719 non-null object
6 WORK_PROVINCE 59740 non-null object
7 WORK_COUNTRY 62962 non-null object
8 AGE 62568 non-null float64
9 LOAD_TIME 62988 non-null object
10 FLIGHT_COUNT 62988 non-null int64
11 BP_SUM 62988 non-null int64
12 EP_SUM_YR_1 62988 non-null int64
13 EP_SUM_YR_2 62988 non-null int64
14 SUM_YR_1 62437 non-null float64
15 SUM_YR_2 62850 non-null float64
16 SEG_KM_SUM 62988 non-null int64
17 WEIGHTED_SEG_KM 62988 non-null float64
18 LAST_FLIGHT_DATE 62988 non-null object
19 AVG_FLIGHT_COUNT 62988 non-null float64
20 AVG_BP_SUM 62988 non-null float64
21 BEGIN_TO_FIRST 62988 non-null int64
22 LAST_TO_END 62988 non-null int64
23 AVG_INTERVAL 62988 non-null float64
24 MAX_INTERVAL 62988 non-null int64
25 ADD_POINTS_SUM_YR_1 62988 non-null int64
26 ADD_POINTS_SUM_YR_2 62988 non-null int64
27 EXCHANGE_COUNT 62988 non-null int64
28 avg_discount 62988 non-null float64
29 P1Y_Flight_Count 62988 non-null int64
30 L1Y_Flight_Count 62988 non-null int64
31 P1Y_BP_SUM 62988 non-null int64
32 L1Y_BP_SUM 62988 non-null int64
33 EP_SUM 62988 non-null int64
34 ADD_Point_SUM 62988 non-null int64
35 Eli_Add_Point_Sum 62988 non-null int64
36 L1Y_ELi_Add_Points 62988 non-null int64
37 Points_Sum 62988 non-null int64
38 L1Y_Points_Sum 62988 non-null int64
39 Ration_L1Y_Flight_Count 62988 non-null float64
40 Ration_P1Y_Flight_Count 62988 non-null float64
41 Ration_P1Y_BPS 62988 non-null float64
42 Ration_L1Y_BPS 62988 non-null float64
43 Point_NotFlight 62988 non-null int64
dtypes: float64(12), int64(24), object(8)
memory usage: 21.1+ MB
- 有大量的列存在缺失值
- 存在8列object数据
查看数据集的重复情况
(62988, 44)
1
| data.drop_duplicates().shape
|
(62988, 44)
说明数据集不存在重复值
查看数据集具体的缺失值情况
MEMBER_NO 0
FFP_DATE 0
FIRST_FLIGHT_DATE 0
GENDER 3
FFP_TIER 0
WORK_CITY 2269
WORK_PROVINCE 3248
WORK_COUNTRY 26
AGE 420
LOAD_TIME 0
FLIGHT_COUNT 0
BP_SUM 0
EP_SUM_YR_1 0
EP_SUM_YR_2 0
SUM_YR_1 551
SUM_YR_2 138
SEG_KM_SUM 0
WEIGHTED_SEG_KM 0
LAST_FLIGHT_DATE 0
AVG_FLIGHT_COUNT 0
AVG_BP_SUM 0
BEGIN_TO_FIRST 0
LAST_TO_END 0
AVG_INTERVAL 0
MAX_INTERVAL 0
ADD_POINTS_SUM_YR_1 0
ADD_POINTS_SUM_YR_2 0
EXCHANGE_COUNT 0
avg_discount 0
P1Y_Flight_Count 0
L1Y_Flight_Count 0
P1Y_BP_SUM 0
L1Y_BP_SUM 0
EP_SUM 0
ADD_Point_SUM 0
Eli_Add_Point_Sum 0
L1Y_ELi_Add_Points 0
Points_Sum 0
L1Y_Points_Sum 0
Ration_L1Y_Flight_Count 0
Ration_P1Y_Flight_Count 0
Ration_P1Y_BPS 0
Ration_L1Y_BPS 0
Point_NotFlight 0
dtype: int64
数据的预处理
结合业务逻辑进行数据预处理
删除票价为空的数据
1 2
| data = data[~data['SUM_YR_1'].isna()] data = data[~data['SUM_YR_2'].isna()]
|
丢弃票价为0,平均折扣率不为0,总飞行公里数大于0的记录
1 2 3 4
| index_yr_1 = data['SUM_YR_1'] == 0 index_yr_2 = data['SUM_YR_2'] == 0 index_avg_discount = data['avg_discount'] != 0 index_seg_km_sum = data['SEG_KM_SUM'] > 0
|
1
| data = data[~(index_yr_1 & index_yr_2 & index_avg_discount & index_seg_km_sum)]
|
特征构造
将入会时间和观测窗口结束时间转化为时间类型的数据
1 2
| data['FFP_DATE'] = pd.to_datetime(data['FFP_DATE']) data['LOAD_TIME'] = pd.to_datetime(data['LOAD_TIME'])
|
构建LRFMC特征
1
| data['L'] = (data['LOAD_TIME'] - data['FFP_DATE']).apply(lambda x: x.days/30)
|
1
| data['R'] = data['LAST_TO_END']
|
1
| data['F'] = data['FLIGHT_COUNT']
|
1
| data['M'] = data['SEG_KM_SUM']
|
1
| data['C'] = data['avg_discount']
|
1
| new_data = data[['L', 'R', 'F', 'M', 'C']]
|
1 2 3 4 5
| from sklearn.preprocessing import StandardScaler
standard_scaler = StandardScaler() new_data = standard_scaler.fit_transform(new_data)
|
对筛选出来的特征进行聚类分析
1
| from sklearn.cluster import KMeans
|
1 2
| K = 5 kmeans_model = KMeans(n_clusters=K)
|
1
| kmeans_model.fit(new_data)
|
KMeans(n_clusters=5)
1 2
| kmeans_model.cluster_centers_
|
array([[ 0.06233588, -0.00491015, -0.22698558, -0.23067735, 2.18473313],
[-0.31475997, 1.68627777, -0.57395798, -0.53669472, -0.17389533],
[ 0.48278764, -0.7994434 , 2.48377146, 2.42496111, 0.30842462],
[ 1.16095498, -0.37732257, -0.0867671 , -0.09463321, -0.159118 ],
[-0.70027213, -0.41492263, -0.16102864, -0.1609829 , -0.2536324 ]])
1 2
| sum(kmeans_model.labels_ == 4)
|
24665
可视化
1 2 3 4 5
| import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] plt.rcParams['axes.unicode_minus'] = False
|
1 2
| ax = plt.subplot(111, polar=True) plt.show()
|
1 2 3
| feature_num = new_data.shape[1] feature_num
|
5
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| angle = list(np.linspace(0, 2*np.pi, feature_num, endpoint=False))
angle.append(angle[0]) angle = np.array(angle)
plt.figure(figsize=(5, 5), dpi=150)
ax = plt.subplot(111, polar=True)
ax.set_title('客户群雷达图')
color = ['r--', 'b--', 'g--', 'y--', 'm--'] for i in range(K): length = list(kmeans_model.cluster_centers_[i]) length.append(length[0]) length = np.array(length) ax.plot(angle, length, color[i])
plt.legend(['客户群体1', '客户群体2', '客户群体3', '客户群体4', '客户群体5']) plt.show()
|
- 客户群体1:乘坐飞机的折扣系数比较大,并且其他几个指标都比较低,说明这类客户只在,机票打折时乘坐飞机,属于低价值客户
- 客户群体2:这类客户最近一次乘坐飞机距离观测窗口结束时间比较长,说明这类客户属于流失客户。
- 客户群体3:这类客户乘坐飞机的次数较高,并且飞行的总里程数也较高,说明这类客户是高价值客户。
- 客户群体4:这类客户注册会员时间距离观测窗口结束时间较大,说明这类客户注册会员的时间较长,属于忠诚客户。
- 客户群体5:这类客户5个指标都比较低,说明这类客户要么是新用户,要么是无价值客户。