航空公司客户价值分析

源自《python数据分析与挖掘实战》

项目目标

  • 借助航空公司客户数据,对客户进行分类
  • 对不同的客户类别进行特征分析,比较不同类别客户的客户价值
  • 对不同价值的客户类别提供个性化服务,制定相应的营销策略

了解客户价值分析

客户营销战略倡导者Jay & Adam Curry从国外数百家公司进行了客户营销实验的经验中提炼了如下经验

  • 公司收入的80%来自顶端的20%的客户。
  • 20%的客户其理论率100%。
  • 90%以上的收入来自现有客户。
  • 大部分的营销预算经常被用在非现有客户上。
  • 5%至30%的客户在客户金字塔中具有升级潜力。
  • 客户金字塔中客户升级2%,意味着销售收入增加10%,利润增加50%。
    这些经验也许并不完全准备,但是它揭示了新时代客户分化的趋势,也说明了对客户价值分析的迫切性和必要性。

模型

RFM模型:最近消费时间间隔(Recency)、消费频率(Frequency)和消费金额(Monetary)

模型解读

由于航空票价受到运输距离,舱位等级等多种因素影响,同样消费金额的不同旅客对航空公司的价值是不同的,因此这个特征并不适用于航空公司的客户价值分析。
LRFMC模型

  • L——会员入会时间距观测窗口结束的月数
  • R——客户最后一次乘坐飞机距观测窗口结束的月数
  • F——客户在观测窗口内乘坐飞机的次数
  • M——客户在观测窗口内的总飞行里程
  • C——客户在观测窗口内乘坐的舱位对应折扣系数的平均值

属性构造

  • L=LOAD_TIME - FFP_DATE(观测窗口的结束时间 - 入会时间)
  • R=LAST_TO_END(最后一次乘坐飞机距观测窗口结束的时长)
  • F=FLIGHT_COUNT(观测窗口内的飞行次数)
  • M=SEG_KM_SUM(观测窗口内的总飞行里程)
  • C=AVG_DISCOUNT(平均折扣率)

数据预处理

数据预分析

统计每个属性的缺失值(空值)个数,并查找最大值和最小值。

explore['null'] = len(data) - explore['count']
explore = explore[['null', 'max', 'min']]
explore.columns = [['空值数','最大值','最小值']]
explore
数据范围

数据清洗

清洗条件

  • 票价为空
  • 票价为0,平均折扣率不为0,总飞行里程数大于0
    处理方法
    满足清洗条件的一行数据全部丢弃。
# 数据清洗, 保留票价非空
data = data[data['SUM_YR_1'].notnull() & data['SUM_YR_2'].notnull()]

# 只保留票价非零, 或者平均折扣率为0的值
index1 = data['SUM_YR_1'] != 0
index2 = data['SUM_YR_2'] != 0
index3 = data['avg_discount'] == 0
data = data[index1 | index2 | index3]

数据标准化

为不同指标数量级不同所带来的影响,对数据进行标准差标准化。

data = (df - df.mean(axis=0))/(df.std(axis=0))
data.columns = ['Z' + i for i in df.columns]

聚类算法

from sklearn.cluster import KMeans

基本概念

K-Means聚类算法是一种基于质心的划分方法,输入聚类个数k,以及包含n个数据对象的数据库,输出满足误差平方和最小标准的k个聚类。算法步骤如下:

  1. 从n个样本数据中随机抽取k个对象作为初始的聚类中心
  2. 分别计算每个样本到各个聚类质心的距离,将样本分配到距离最近的那个聚类中心类别中
  3. 所有样本分配完成后,重新计算k个聚类的中心
  4. 与前一次计算得到的k个聚类中心比较,如果聚类中心发生变化,转(2),否者转(5)
  5. 当质心不发生变化时,停止并输出聚类结果
def __init__(self, n_clusters=8, init='k-means++', 
n_init=10, max_iter=300,tol=1e-4,precompute_distances='auto',
verbose=0, random_state=None, copy_x=True, n_jobs=1):

输入参数:

(1)n_clusters:要分成的簇数也是要生成的质心数

类型:整数型(int

默认值:8

n_clusters : int, optional, default: 8

The number of clusters to form as well as the number of centroids to generate.

(2)init:初始化质心

类型:可以是function 可以是array(random or ndarray)

默认值:采用k-means++(一种生成初始质心的算法)

kmeans++:种子点选取的第二种方法。

kmedoids(PAM,Partitioning Around Medoids)

能够解决kmeans对噪声敏感的问题。kmeans寻找种子点的时候计算该类中所有样本的平均值,如果该类中具有较为明显的离群点,会造成种子点与期望偏差过大。例如,A(1,1),B(2,2),C(3,3),D(1000,1000),显然D点会拉动种子点向其偏移。这样,在下一轮迭代时,将大量不该属于该类的样本点错误的划入该类。

为了解决这个问题,kmedoids方法采取新的种子点选取方式,1)只从样本点中选;2)选取标准能够提高聚类效果,例如上述的最小化J函数,或者自定义其他的代价函数。但是,kmedoids方法提高了聚类的复杂度。

init : {'k-means++', 'random' or an ndarray}

Method for initialization, defaults to 'k-means++':
'k-means++' : selects initial cluster centers for k-mean clustering in
a smart way to speed up convergence. See section Notes in k_init for more details.

(3)n_init: 设置选择质心种子次数,默认为10次。返回质心最好的一次结果(好是指计算时长短)

类型:整数型(int

默认值:10

目的:每一次算法运行时开始的centroid seeds是随机生成的, 这样得到的结果也可能有好有坏. 所以要运行算法n_init次, 取其中最好的。

n_init : int, default: 10

Number of time the k-means algorithm will be run with different centroid seeds.
The final results will be the best output of n_init consecutive runs in terms of inertia.

(4)max_iter:每次迭代的最大次数

类型:整型(int

默认值:300

max_iter : int, default: 300

Maximum number of iterations of the k-means algorithm for a
single run.

(5)tol: 容忍的最小误差,当误差小于tol就会退出迭代(算法中会依赖数据本身)

类型:浮点型(float

默认值:le-4(0.0001)

Relative tolerance with regards to inertia to declare convergence

(6)precompute_distances: 这个参数会在空间和时间之间做权衡,如果是True 会把整个距离矩阵都放到内存中,auto 会默认在数据样本大于featurs*samples 的数量大于12e6 的时候False,False时核心实现的方法是利用Cpython 来实现的

类型:布尔型(autoTrueFalse

默认值:auto

Precompute distances (faster but takes more memory).
'auto' : do not precompute distances if n_samples * n_clusters > 12 million. This corresponds to about 100MB overhead per job usingdouble precision.

(7)verbose:是否输出详细信息

类型:布尔型(TrueFalse

默认值:False

verbose : boolean, optional
Verbosity mode.

(8)random_state: 随机生成器的种子 ,和初始化中心有关

类型:整型或numpy(RandomState, optional)

默认值:None

random_state : integer or numpy.RandomState, optional
The generator used to initialize the centers. If an integer is given, it fixes the seed. Defaults to the global numpy random number generator.

(9)copy_xboolscikit-learn 很多接口中都会有这个参数的,就是是否对输入数据继续copy 操作,以便不修改用户的输入数据。这个要理解Python 的内存机制才会比较清楚。

类型:布尔型(boolean, optional)

默认值:True

When pre-computing distances it is more numerically accurate to center the data first. If copy_x is True, then the original data is not modified. If False, the original data is modified, and put back before the function returns, but small numerical differences may be introduced by subtracting and then adding the data mean.

(10)n_jobs: 使用进程的数量,与电脑的CPU有关

类型:整数型(int

默认值:1

The number of jobs to use for the computation. This works by computing
each of the n_init runs in parallel.
If -1 all CPUs are used. If 1 is given, no parallel computing code is used at all, which is useful for debugging. For n_jobs below -1,(n_cpus + 1 + n_jobs) are used. Thus for n_jobs = -2, all CPUs but one
are used.

(二)输出参数:

(1)label_:每个样本对应的簇类别标签

示例:r1 = pd.Series(model.labels_).value_counts() #统计各个类别的数目

(2)cluster_centers_:聚类中心

返回值:array, [n_clusters, n_features]

示例:r2 = pd.DataFrame(model.cluster_centers_) #找出聚类中心

聚类代码

from sklearn.cluster import KMeans
k = 5
kmodel = KMeans(n_clusters = k, n_jobs = 4)
kmodel.fit(data)   # 训练数据
# 查看聚类中心
kmodel.cluster_centers_
array([[ 0.05413636, -0.00294837, -0.22884398, -0.23289087,  2.18362792],
       [ 1.16107019, -0.37746281, -0.0866874 , -0.09471551, -0.15729059],
       [-0.31407344,  1.68560841, -0.57386122, -0.53668581, -0.1753762 ],
       [ 0.48302008, -0.79948458,  2.48279483,  2.42422366,  0.30947997],
       [-0.7000998 , -0.4153057 , -0.16094143, -0.16073752, -0.25434129]])

分析聚类结果

聚类类别与个数

聚类分群结果

画出客户群体特征雷达图:

雷达图

客户群1:紫色
客户群2:橙色
客户群3:绿色
客户群4:红色
客户群5:蓝色

由图可以看出,客户群1数量最大,所乘航班折扣率很低,加入会员时间短,这类客户一般在机票打折时,才会乘坐公司航班,属于一般客户。客户群2数量较大,加入会员时间长,但乘坐频率变小,属于重要挽留客户。客户群3数量中,乘坐次数很少,乘坐里程很小,很长时间没有乘坐公司航班,属于低价值客户。客户群4数量小,乘坐次数很多,乘坐里程很大,所乘航班折扣率较高,属于重要保持客户。客户群5数量小,所乘航班折扣率很高,属于重要发展客户。
客户价值排名:重要保持客户(4)>重要发展客户(5)>重要挽留客户(2)>一般客户(1),客户群3是低价值客户。

模型应用

  • 对于数量极少的客户群4,进行一对一精准营销。
  • 对于数量极少的客户群5,实行里程数兑换机票。
  • 对于数量较大的客户群2,提供会员升级提醒服务。
  • 积极和非航空类企业合作,顾客在合作企业消费也可获得本航空公司奖励,增加客户与公司的联系。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,001评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,210评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,874评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,001评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,022评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,005评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,929评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,742评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,193评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,427评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,583评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,305评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,911评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,564评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,731评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,581评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,478评论 2 352

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,650评论 18 139
  • 文/关长天 北行路上,车走的很慢 一行秋雨如泪,游落窗边 人们怀着心事,但绝无声息 在喧闹中我总是沉默 安静时便有...
    关长天阅读 419评论 25 79
  • Sunny飞镜阅读 173评论 0 0
  • 昨天召开战略解码会,确定明年的任务分解。虽然此前费尽心力与各个部门沟通,但还是有一项重要指标无法落实,责任部门以各...
    叶荫先生阅读 114评论 0 1