1.RFM分析
根据客户活跃程度和交易金额贡献,进行客户价值细分的方法。
指标 | 解释 | 意义 |
---|---|---|
Recency近度 | 客户最近一次交易时间到现在的间隔 | R越大,越久未发生交易;R越小,越近有交易发生 |
Frequency频度 | 客户最近一段时间内交易的次数 | F越大,客户交易越频繁;F越小,客户不够活跃 |
Monetary额度 | 客户最近一段时间内交易的金额 | M越大,客户价值越高;M越小,客户价值越低 |
R_S分类 | F_S分类 | M_S分类 | 客户类型 |
---|---|---|---|
高 | 高 | 高 | 高价值客户 |
低 | 高 | 高 | 重点保持客户 |
高 | 低 | 高 | 重点发展客户 |
低 | 低 | 高 | 重点挽留客户 |
高 | 高 | 低 | 一般价值客户 |
低 | 高 | 低 | 一般保持客户 |
高 | 低 | 低 | 一般发展客户 |
低 | 低 | 低 | 潜在客户 |
1.1 RFM分析过程
1.计算RFM各项分值
- R_S:距离当前日期越近,得分越高,最高5分,最低1分。
- F_S:交易频率越高,得分越高,最高5分,最低1分。
- M_S:交易金额越高,得分越高,最高5分,最低1分。
2.汇总RFM分值
RFM=100*R_S+10*F_S+1*M_S
3.根据RFM分值对客户划分8种类型
1.2 RFM分析前提
1.最近有过交易行为的客户,再次发生交易的可能性要高于最近没有交易行为的客户。
2.交易频率较高的客户比交易频率较低的客户,更有可能再次发生交易行为。
3.过去所有交易总金额较多的客户,比交易总金额较少的客户,更有消费积极性。
1.3 RFM计算过程
import pandas
import numpy
data = pandas.read_csv(
'/users/bakufu/desktop/5.7/data.csv'
)
Out[37]:
OrderID CustomerID DealDateTime Sales
0 4529 34858 2014-05-14 807
1 4532 14597 2014-05-14 160
2 4533 24598 2014-05-14 418
3 4534 14600 2014-05-14 401
4 4535 24798 2014-05-14 234
5 4536 44856 2014-05-14 102
6 4558 34695 2014-05-14 130
7 4559 24764 2014-05-14 377
8 4566 34765 2014-05-15 466
9 4567 34581 2014-05-15 821
10 4568 44637 2014-05-15 84
... ... ... ...
15866 54843 24686 2015-09-25 683
[15867 rows x 4 columns]
data['DealDateTime'] = pandas.to_datetime(
data.DealDateTime,
format='%Y/%m/%d'
)
Out[37]:
OrderID CustomerID DealDateTime Sales
0 4529 34858 2014-05-14 807
1 4532 14597 2014-05-14 160
2 4533 24598 2014-05-14 418
3 4534 14600 2014-05-14 401
4 4535 24798 2014-05-14 234
5 4536 44856 2014-05-14 102
6 4558 34695 2014-05-14 130
7 4559 24764 2014-05-14 377
8 4566 34765 2014-05-15 466
9 4567 34581 2014-05-15 821
10 4568 44637 2014-05-15 84
... ... ... ...
15866 54843 24686 2015-09-25 683
[15867 rows x 4 columns]
data['DateDiff'] = pandas.to_datetime(
'today'
) - data['DealDateTime']
Out[41]:
OrderID CustomerID DealDateTime Sales DateDiff
0 4529 34858 2014-05-14 807 1515 days
1 4532 14597 2014-05-14 160 1515 days
2 4533 24598 2014-05-14 418 1515 days
3 4534 14600 2014-05-14 401 1515 days
4 4535 24798 2014-05-14 234 1515 days
5 4536 44856 2014-05-14 102 1515 days
6 4558 34695 2014-05-14 130 1515 days
7 4559 24764 2014-05-14 377 1515 days
8 4566 34765 2014-05-15 466 1514 days
9 4567 34581 2014-05-15 821 1514 days
10 4568 44637 2014-05-15 84 1514 days
... ... ... ... ...
15866 54843 24686 2015-09-25 683 1016 days
[15867 rows x 5 columns]
data['DateDiff'] = data['DateDiff'].dt.days
Out[43]:
OrderID CustomerID DealDateTime Sales DateDiff
0 4529 34858 2014-05-14 807 1515
1 4532 14597 2014-05-14 160 1515
2 4533 24598 2014-05-14 418 1515
3 4534 14600 2014-05-14 401 1515
4 4535 24798 2014-05-14 234 1515
5 4536 44856 2014-05-14 102 1515
6 4558 34695 2014-05-14 130 1515
7 4559 24764 2014-05-14 377 1515
8 4566 34765 2014-05-15 466 1514
9 4567 34581 2014-05-15 821 1514
10 4568 44637 2014-05-15 84 1514
... ... ... ... ...
15866 54843 24686 2015-09-25 683 1016
[15867 rows x 5 columns]
R_Agg = data.groupby(
by=['CustomerID']
)['DateDiff'].agg({
'RecencyAgg': numpy.min
})
Out[45]:
RecencyAgg
CustomerID
14568 1024
14569 1114
14570 1044
14571 1084
14572 1108
14573 1094
14574 1019
14575 1019
14576 1069
14577 1030
... ...
44867 1107
[1200 rows x 1 columns]
F_Agg = data.groupby(
by=['CustomerID']
)['OrderID'].agg({
'FrequencyAgg': numpy.size
})
Out[47]:
RecencyAgg
CustomerID
14568 15
14569 12
14570 15
14571 15
14572 8
14573 10
14574 15
14575 17
14576 13
14577 8
... ...
44867 10
[1200 rows x 1 columns]
M_Agg = data.groupby(
by=['CustomerID']
)['Sales'].agg({
'MonetaryAgg': numpy.sum
})
Out[49]:
MonetaryAgg
CustomerID
14568 6255
14569 5420
14570 8261
14571 8124
14572 3334
14573 4358
14574 8506
14575 7432
14576 6481
14577 2737
... ...
44867 4187
[1200 rows x 1 columns]
aggData = R_Agg.join(F_Agg).join(M_Agg)
Out[51]:
RecencyAgg FrequencyAgg MonetaryAgg
CustomerID
14568 1024 15 6255
14569 1114 12 5420
14570 1044 15 8261
14571 1084 15 8124
14572 1108 8 3334
14573 1094 10 4358
14574 1019 15 8506
14575 1019 17 7432
14576 1069 13 6481
14577 1030 8 2737
... ... ...
44867 1107 10 4187
[1200 rows x 3 columns]
bins = aggData.RecencyAgg.quantile(
q=[0, 0.2, 0.4, 0.6, 0.8, 1],
interpolation='nearest'
)
Out[53]:
0.0 1016
0.2 1023
0.4 1035
0.6 1050
0.8 1069
1.0 1281
Name: RecencyAgg, dtype: int64
bins[0] = 0
labels = [5, 4, 3, 2, 1]
R_S = pandas.cut(
aggData.RecencyAgg,
bins, labels=labels
)
Out[56]:
0.0 0
0.2 1023
0.4 1035
0.6 1050
0.8 1069
1.0 1281
Name: RecencyAgg, dtype: int64
bins = aggData.FrequencyAgg.quantile(
q=[0, 0.2, 0.4, 0.6, 0.8, 1],
interpolation='nearest'
)
Out[58]:
0.0 4
0.2 10
0.4 12
0.6 14
0.8 16
1.0 25
Name: FrequencyAgg, dtype: int64
bins[0] = 0;
labels = [1, 2, 3, 4, 5];
F_S = pandas.cut(
aggData.FrequencyAgg,
bins, labels=labels
)
Out[60]:
0.0 0
0.2 10
0.4 12
0.6 14
0.8 16
1.0 25
Name: FrequencyAgg, dtype: int64
bins = aggData.MonetaryAgg.quantile(
q=[0, 0.2, 0.4, 0.6, 0.8, 1],
interpolation='nearest'
)
Out[62]:
0.0 735
0.2 4840
0.4 5890
0.6 7036
0.8 8283
1.0 13460
Name: MonetaryAgg, dtype: int64
bins[0] = 0;
labels = [1, 2, 3, 4, 5]
M_S = pandas.cut(
aggData.MonetaryAgg,
bins, labels=labels
)
Out[64]:
0.0 0
0.2 4840
0.4 5890
0.6 7036
0.8 8283
1.0 13460
Name: MonetaryAgg, dtype: int64
aggData['R_S']=R_S
aggData['F_S']=F_S
aggData['M_S']=M_S
Out[66]:
RecencyAgg FrequencyAgg MonetaryAgg R_S F_S M_S
CustomerID
14568 1024 15 6255 4 4 3
14569 1114 12 5420 1 2 2
14570 1044 15 8261 3 4 4
14571 1084 15 8124 1 4 4
14572 1108 8 3334 1 1 1
14573 1094 10 4358 1 1 1
14574 1019 15 8506 5 4 5
14575 1019 17 7432 5 5 4
14576 1069 13 6481 2 3 3
14577 1030 8 2737 4 1 1
... ... ... .. .. ..
44867 1107 10 4187 1 1 1
[1200 rows x 6 columns]
aggData['RFM'] = 100*R_S.astype(int) + 10*F_S.astype(int) + 1*M_S.astype(int)
Out[68]:
RecencyAgg FrequencyAgg MonetaryAgg R_S F_S M_S RFM
CustomerID
14568 1024 15 6255 4 4 3 443
14569 1114 12 5420 1 2 2 122
14570 1044 15 8261 3 4 4 344
14571 1084 15 8124 1 4 4 144
14572 1108 8 3334 1 1 1 111
14573 1094 10 4358 1 1 1 111
14574 1019 15 8506 5 4 5 545
14575 1019 17 7432 5 5 4 554
14576 1069 13 6481 2 3 3 233
14577 1030 8 2737 4 1 1 411
... ... ... .. .. .. ...
44867 1107 10 4187 1 1 1 111
[1200 rows x 7 columns]
bins = aggData.RFM.quantile(
q=[
0, 0.125, 0.25, 0.375, 0.5,
0.625, 0.75, 0.875, 1
],
interpolation='nearest'
)
Out[70]:
0.000 111
0.125 131
0.250 222
0.375 254
0.500 334
0.625 422
0.750 454
0.875 532
1.000 555
Name: RFM, dtype: int64
bins[0] = 0
labels = [1, 2, 3, 4, 5, 6, 7, 8]
aggData['level'] = pandas.cut(
aggData.RFM,
bins, labels=labels
)
Out[72]:
0.000 0
0.125 131
0.250 222
0.375 254
0.500 334
0.625 422
0.750 454
0.875 532
1.000 555
Name: RFM, dtype: int64
aggData = aggData.reset_index()
Out[74]:
CustomerID RecencyAgg FrequencyAgg MonetaryAgg R_S F_S M_S RFM level
0 14568 1024 15 6255 4 4 3 443 6
1 14569 1114 12 5420 1 2 2 122 1
2 14570 1044 15 8261 3 4 4 344 5
3 14571 1084 15 8124 1 4 4 144 2
4 14572 1108 8 3334 1 1 1 111 1
5 14573 1094 10 4358 1 1 1 111 1
6 14574 1019 15 8506 5 4 5 545 8
7 14575 1019 17 7432 5 5 4 554 8
8 14576 1069 13 6481 2 3 3 233 3
9 14577 1030 8 2737 4 1 1 411 5
... ... ... ... .. .. .. ... ...
1199 44867 1107 10 4187 1 1 1 111 1
[1200 rows x 9 columns]
aggData.sort_values(
['level', 'RFM'],
ascending=[1, 1]
)
Out[75]:
CustomerID RecencyAgg FrequencyAgg MonetaryAgg R_S F_S M_S RFM level
4 14572 1108 8 3334 1 1 1 111 1
5 14573 1094 10 4358 1 1 1 111 1
42 14610 1075 7 3685 1 1 1 111 1
59 14627 1076 8 3809 1 1 1 111 1
81 14649 1092 5 735 1 1 1 111 1
82 14650 1122 6 3074 1 1 1 111 1
101 14669 1106 6 2708 1 1 1 111 1
117 14685 1078 9 3839 1 1 1 111 1
123 14691 1091 10 3538 1 1 1 111 1
144 14712 1142 8 3788 1 1 1 111 1
... ... ... ... .. .. .. ... ...
1188 44856 1017 23 10852 5 5 5 555 8
[1200 rows x 9 columns]
aggData.groupby(
by=['level']
)['CustomerID'].agg({
'size': numpy.size
})
Out[76]:
size
level
1 153
2 164
3 135
4 153
5 154
6 142
7 151
8 148
2.矩阵分析
根据事物(如产品、服务等)等两个重要指标作为分析依据,进行关联分析,找出解决问题等一种分析方法。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import pandas
import matplotlib
import matplotlib.pyplot as plt
#定义主题颜色,使用RGB方式
mainColor = (42/256, 87/256, 141/256, 1);
#设置字体
font = {
'family': 'Menlo',
'size': 20
}
matplotlib.rc('font', **font);
data = pandas.read_csv(
'/users/bakufu/desktop/5.8/data.csv'
)
Out[2]:
province GDP population
0 天津 1572247 14945
1 北京 2133083 21332
2 上海 2356094 24204
3 江苏 6508832 79498
4 浙江 4015350 55030
5 内蒙古 1776951 25012
6 辽宁 2862658 43907
7 福建 2405576 37900
8 广东 6779224 106840
9 山东 5942659 97614
10 吉林 1380381 27518
11 重庆 1426540 29807
12 湖北 2736704 58075
13 陕西 1768994 37696
14 宁夏 275210 6579
15 新疆 926410 22814
16 湖南 2704846 67139
17 河北 2942115 73582
18 青海 230112 5806
19 黑龙江 1503938 38446
20 海南 350072 8994
21 四川 2853666 81236
22 山西 1275944 36389
23 河南 3493938 100377
24 江西 1570859 45322
25 安徽 2084875 60564
26 广西 1567297 47365
27 西藏 92083 3148
28 云南 1281459 47003
29 甘肃 683527 25865
30 贵州 925101 35051
#如果数据点很多可以调大尺寸
fig = plt.figure(
figsize=(30, 20),
dpi=80
)
#将图形分为一行一列, 当前操作第一个子图
sp = fig.add_subplot(111)
sp.set_xlim([
0,
data.GDP.max()*1.1
])
sp.set_ylim([
0,
data.population.max()*1.1
])
#关闭坐标轴、坐标轴的刻度值
#sp.axis('off')
sp.get_xaxis().set_ticks([])
sp.get_yaxis().set_ticks([])
#画点
sp.scatter(
data.GDP, data.population,
alpha=0.5, s=200, marker="o",
edgecolors=mainColor, linewidths=5
)
#画均值线
sp.axvline(
x=data.GDP.mean(),
linewidth=1, color=mainColor
)
sp.axhline(
y=data.population.mean(),
linewidth=1, color=mainColor
)
sp.axvline(
x=0,
linewidth=3, color=mainColor
)
sp.axhline(
y=0,
linewidth=3, color=mainColor
)
sp.set_xlabel('GDP')
sp.set_ylabel('人口')
#画标签
data.apply(
lambda row: plt.text(
row.GDP,
row.population,
row.province,
fontsize=15
),
axis=1
)
plt.show()