基于RFM 模型的 Python 实战分析
基于RFM 模型的 Python 实战分析
一、RFM 模型介绍
RFM模型是根据客户活跃程度和交易金额的贡献,进行客户价值细分的一种用户分类方法。
- R(Recency)——最近一次交易时间间隔。基于最近一次交易日期计算的得分,距离当前日期越近,得分越高。如5分制反映客户交易活跃度较高。
- F(Frequency)——客户在最近一段时间内交易次数。基于交易频率计算的得分,交易频率越高,得分越高。如5分制反映客户交易频次较高。
- M(Monetray)——客户最近一段时间内交易金额。基于交易金额计算的得分,交易金额越高,得分越高。如5分制反映客户交易金额较高。
以上三个指标对客户进行 每个维度的1-5 分打分,会将每个维度细分出5类,这样就能够细分出共5x5x5=125类用户。
但一般来说125类用户已超出普通人脑的计算范畴了,更别说针对125类用户量体定制营销策略。
在本次实战中,我们只把每个维度做一次两分,即在每个维度上取平均值,高于平均值取 1,低于平均值取 0。
这样在3个维度上我们得到了2* 2*2=8类用户。
用户分类 | R 分类 | F 分类 | M 分类 | 解读 |
---|---|---|---|---|
重要价值客户 | 1 | 1 | 1 | 最近消费、高频、高消费 |
消费潜力客户 | 1 | 1 | 0 | 最近消费、高频、低消费 |
频次深耕客户 | 1 | 0 | 1 | 最近消费、低频、高消费 |
新客户 | 1 | 0 | 0 | 最近消费、低频、低消费 |
重要价值流失预警客户 | 0 | 1 | 1 | 最近未消费、高频、高消费 |
一般客户 | 0 | 1 | 0 | 最近未消费、高频、低消费 |
高消费换回客户 | 0 | 0 | 1 | 最近未消费、低频、高消费 |
流失客户 | 0 | 0 | 0 | 最近未消费、低频、低消费 |
基于这 8 类用户,我们再进行用户营销策略制定,显而易见会容易许多。
二、数据导入与清洗
1.相关包导入
先对相关包进行导入,将数据导入 Python:
import pandas as pd
import numpy as np
df=pd.read_csv('RMF_Model_Data.csv')
2.查看字段定义
查看数据表中相关字段及其含义:
df.columns
由于本次数据只需提取已完成的订单,故对【订单状态】查看其状态:
a=df.groupby('订单状态')['订单编号'].count().reset_index()
3.提取有用字段
由上可知:数据表中订单存在3种类型状态,订单未支付、订单支付未评价、订单已支付已评价。
上述 3 种订单均为已完成的订单,故无需对订单状态字段进行处理。
RFM模型中仅需 乘客编号,订单时间,订单金额,故将数据字段进行精简,仅保留以上 3 个字段。
df=df[['乘客编号','订单金额','叫车时间']]
df.head()
4.数据清洗
运行后发现叫车时间存在转义符,需对其进行处理:
(此处即对叫车时间进行切片,丢弃其最后两个字符)
df['叫车时间']=df['叫车时间'].apply(lambda x: x[:-2])
df.head()
查看数据类型,看是否有丢失或残缺:
df.info()
各字段数据完整,均为 31809条,无丢失情况。
但同时也发现,乘客编号为浮点型、订单金额为整型,叫车时间却为object类型。
下面利用 pandas将其转换为时间格式:
(此处是为了后续作时序分析,若只进行 RFM 模型,可以不进行转换)
df['叫车时间']=pd.to_datetime(df['叫车时间'],format='%Y/%m/%d %H:%M:%S')
df.info()
6.补充知识(日期格式化表达式)
插播一个小知识:Python 中日期格式化的表达方式如下:
%y 两位数的年份表示(00-99)
%Y 四位数的年份表示(000-9999)
%m 月份(01-12)
%d 月内中的一天(0-31)
%H 24小时制小时数(0-23)
%I 12小时制小时数(01-12)
%M 分钟数(00-59)
%S 秒(00-59)
%a 本地简化星期名称
%A 本地完整星期名称
%b 本地简化的月份名称
%B 本地完整的月份名称
%c 本地相应的日期表示和时间表示
%j 年内的一天(001-366)
%p 本地A.M.或P.M.的等价符
%U 一年中的星期数(00-53)星期天为星期的开始
%w 星期(0-6),星期天为星期的开始
%W 一年中的星期数(00-53)星期一为星期的开始
%x 本地相应的日期表示
%X 本地相应的时间表示
%Z 当前时区的名称
%% %号本身
最后我们的清洗基本上是完成了,来看一下清洗完的数据长什么样:
三、RFM 模型建立:
基础清洗告一段落,这一步关键在于构建模型所需的三个字段:
R(最近一次购买距今多少天);
F(购买了多少次);
M(平均或者累计购买金额);
下面开始构造上述三个相关的衡量指标,即最近一次购买距今的天数差R、消费频率F、消费金额M及创建新表RFM。
1、 R 字段的构造:
先求出每位乘客的最近一次叫车时间:
r=df.groupby('乘客编号')['叫车时间'].max().reset_index()
#获得每一位乘客的最近一次叫车时间
r.loc[:10]
再以获取数据的时间(2020/3/1)减去叫车时间,即为R:
r['R']=(pd.to_datetime('2020-3-1')-r['叫车时间']).dt.days
r=r[['乘客编号','R']]
r.loc[:10]
2、F 字段的构造
由于叫车时间为年月日时分秒的格式,故我们要先获得一个日期标签:
df['日期标签']=df['叫车时间'].astype(str).str[:10]
df.head()
一般建立 RFM 模型时,我们会将客户一天内的多笔订单视为一笔
即将以乘客编号&日期标签作聚合,获得各个乘客在 每一天的打车频次:
df_1=df.groupby(['乘客编号','日期标签'])['叫车时间'].count().reset_index()
df_1.loc[:10]
再以乘客编号作聚合,获得乘客在 2 月当月的打车天数:
f=df_1.groupby('乘客编号')['日期标签'].count().reset_index()
f.columns=['乘客编号','F']
f.head()
3、M 字段的构造:
M(每日平均下单金额)= 乘客总下单金额 / F(购买频次)
先求乘客总下单金额:
sum_m=df.groupby('乘客编号')['订单金额'].sum().reset_index()
sum_m.columns=['乘客编号','2月总支付金额']
sum_m.head()
以乘客编号为依据对频次表和总金额表进行表连接:
sum_to_f=pd.merge(sum_m,f,left_on='乘客编号',right_on='乘客编号',how='inner')
sum_to_f.head()
计算用户平均每天的打车金额:
sum_to_f['M']=sum_to_f['2月总支付金额']/sum_to_f['F']
sum_to_f.head()
4、组合R/F/M 字段:
依旧使用 Pandas 的表连接功能:
#将 RFM 三个指标进行合并
rfm=pd.merge(r,sum_to_f,left_on='乘客编号',right_on='乘客编号',how='inner')
rfm=rfm[['乘客编号','R','F','M']]
rfm.head()
5、维度打分:
经过上面的处理,我们已经获得每个乘客的R\F\M 值,但由于他们各自之间数值的差距仍旧较大,所以我们下一步要对上述 RFM 数值进行维度打分,一般情况下分为 1分-5 分;
在我们不知道怎么去获取维度指标,也就是数据分组时,可以先看下 RFM 的描述性统计量:
rfm.describe()
由上可知:
R(最近一次打车距今天数):
R 值的平均值为 8.9 天:乘客最近一次打车距今平均已经 8.9 天;
R 值的最小值为 0 天:存在乘客在统计日当天下单;
R 值的最大值为 29 天:按照2020 年 2 月有 29 天计算,有乘客自 2 月 1 日下单后再无下单行为;
2 月所有下过单的用户中:25%的乘客在最近2天内有下单行为;
2 月所有下过单的用户中:50%的乘客在最近6天内有下单行为;
2 月所有下过单的用户中:75%的乘客在最近15天内有下单行为;
F(2月打车频次):
F 值的平均值为 2.58次:乘客平均 2月有 2.58天有下单行为 ;
F 值的最小值为 0 天:乘客 2月下单天数最少为 1 天;
F 值的最大值为 26 天:本月的29 天中最高有乘客有 26 天都有下单行为,可谓是忠实老客户;
2 月所有下过单的用户中:25%的乘客都只在其中某一天下单;
2 月所有下过单的用户中:50%的乘客都只在其中某一天下单;
2 月所有下过单的用户中:75%的乘客下单天数都集中在在 3天或以下;
M(平均每日下单金额):
M 值的平均值为40.5元:所有乘客日均下单金额为 40.5 元 ;
M 值的最小值为 10 元:乘客日均下单金额最小值为 10 元;
M 值的最大值为 654 元:乘客日均下单金额最大值为 654元;
一般来说分值的大小决定偏好,分数越高,说明我们越喜欢该行为。
对于乘客最近一天乘车时间来说,R 越大,说明用户未下单时间越长,故应设置 R 越大,分值越小;
对于 F和 M 来说,乘客叫车频次越高、平均支付金额越大,说明乘客对平台的黏性越大,故这F\M 应设置为越大,分值越小;
RFM 模型中,一般打分采取五分制,按照对业务的理解,和上述描述性分析情况;
分值划分如下:
5分 | 4 分 | 3 分 | 2 分 | 1 分 | |
---|---|---|---|---|---|
R-SCORE | [0-3) | [3-7) | [7-14) | [14-21) | [21-30) |
F-SCORE | [5,∞) | 4 | 3 | 2 | 1 |
M-SCORE | [100,∞) | [50,100) | [30,50) | [15,30) | [0-15) |
用 pandas 对数据进行分桶:
rfm['R-SCORE']=pd.cut(rfm['R'],bins=[0,3,7,14,21,30],labels=[5,4,3,2,1],right=False).astype(float)
rfm['F-SCORE']=pd.cut(rfm['F'],bins=[1,2,3,4,5,100],labels=[1,2,3,4,5],right=False).astype(float)
rfm['M-SCORE']=pd.cut(rfm['M'],bins=[0,15,30,50,100,10000],labels=[1,2,3,4,5],right=False).astype(float)
运行后查看表结果如下:
每一位乘客都基于 RFM 获得了相应的维度打分;
6、用户标签获取
根据本文开头的分析:
三个指标对客户进行 每个维度的1-5 分打分,会将每个维度细分出5类,这样就能够细分出共5x5x5=125类用户。
但一般来说125类用户已超出普通人脑的计算范畴了,更别说针对125类用户量体定制营销策略。
实际运用上,我们只需要把每个维度做一次两分即可,即在每个维度上取平均值,高于平均值取 1,低于平均值取 0;
故对每位乘客的 RFM分别对其平均值作分析,获得一个布尔值;
将该布尔值*1 可获得相应0 或 1 标签:
rfm['R是否大于平均值']=(rfm['R-SCORE']>rfm['R-SCORE'].mean())*1
rfm['F是否大于平均值']=(rfm['F-SCORE']>rfm['F-SCORE'].mean())*1
rfm['M是否大于平均值']=(rfm['M-SCORE']>rfm['M-SCORE'].mean())*1
运行结果如下:
将三项评价标准串联,获取人群数值打分项:
人群数值=R100+F10+M*1
rfm['数值标签']=(rfm['R是否大于平均值']*100+rfm['F是否大于平均值']*10+rfm['M是否大于平均值']*1)
根据上述对值标签的名称定义:
用户分类 | R 分类 | F 分类 | M 分类 | 解读 | 数值标签 |
---|---|---|---|---|---|
重要价值客户 | 1 | 1 | 1 | 最近消费、高频、高消费 | 111 |
消费潜力客户 | 1 | 1 | 0 | 最近消费、高频、低消费 | 110 |
频次深耕客户 | 1 | 0 | 1 | 最近消费、低频、高消费 | 101 |
新客户 | 1 | 0 | 0 | 最近消费、低频、低消费 | 100 |
重要价值流失预警客户 | 0 | 1 | 1 | 最近未消费、高频、高消费 | 11 |
一般客户 | 0 | 1 | 0 | 最近未消费、高频、低消费 | 10 |
高消费换回客户 | 0 | 0 | 1 | 最近未消费、低频、高消费 | 1 |
流失客户 | 0 | 0 | 0 | 最近未消费、低频、低消费 | 0 |
构造相应的转换标签函数:
def transform_label(s):
if s==111:
label='重要价值客户'
elif s==110:
label='消费潜力客户'
elif s==101:
label='频次深耕客户'
elif s==100:
label='新客户'
elif s==11:
label='重要价值流失预警客户'
elif s==10:
label='一般客户'
elif s==1:
label='高消费挽回客户'
elif s==0:
label='流失客户'
return label
rfm['人群类型']=rfm['人群标签'].apply(transform_label)
运行结果如下:
至此,我们就完成了数据建模,每个用户都获得其相应的用户标签。
四、数据可视化
1、各用户群人数&占比分析:
以人群类型进行聚合:
count=rfm['人群类型'].value_counts().reset_index()
count.columns=['用户类型','人数']
count['人数占比']=count['人数']/count['人数'].sum()
获得 count 数据表如下:
可视化展示:不同类型用户人数分析
plt.rcParams['font.family']=['Arial Unicode MS']
plt.figure(figsize=(8,3),dpi=100)
y=count['人数']
x=count['用户类型']
plt.barh(x,height=0.5,width=y)
plt.title('不同类型用户人数对比')
for x,y in enumerate(y):
plt.text(y+150,x,y,ha='center',va='center',fontsize=10)
plt.xticks(np.arange(0,3001,500))
plt.tight_layout()
plt.savefig('不同类型用户人数对比',dpi=300)
绘制图形如下:
#可视化展示:不同类型用户人数占比分析
plt.rcParams['font.family']=['Arial Unicode MS']
plt.figure(figsize=(8,3),dpi=100)
y=count['人数占比']
x=count['用户类型']
plt.barh(x,height=0.5,width=y)
plt.title('不同类型用户人数占比对比')
for x,y in enumerate(y):
plt.text(y+0.01,
x,str(y*100)[:4]+'%',
ha='center',va='center',
fontsize=10)
plt.xticks(np.arange(0,0.4,0.1))
plt.tight_layout()
plt.savefig('不同类型用户人数占比对比',dpi=300)
绘制图形如下:
由上图可知,所有用户类型中:
高消费挽回类客户人数最多,占比 25.7%。
其中高消费挽回类客户的定义为:最近未消费、低频、高消费。
对于此类用户的针对策略为发放大额门槛优惠券,如满50减8元优惠券等,来刺激用户消费积极性;
频次深耕用户+重要价值用户占比 33%,对于此类用户的针对策略为发放多张门槛优惠组合券包,如满 50 减 8 元+满 30 减 5 元+满20减 3 元等组合券包来刺激用户消费积极性;
2、各用户群消费金额分析:
先构建各用户群体的消费总金额 mon 数据表:
rfm['消费总金额']= rfm['F'] * rfm['M']
mon=rfm.groupby('人群类型')['消费总金额'].sum().reset_index()
mon.columns=['用户类型','消费总金额']
mon['消费占比']=mon['消费总金额']/mon['消费总金额'].sum()
运行后mon 如下所示:
绘制用户类型与消费总金额或消费占比的图表:
#可视化展示:不同类型用户消费总金额分析
plt.rcParams['font.family']=['Arial Unicode MS']
plt.figure(figsize=(8,3),dpi=100)
y=mon['消费总金额']
x=mon['用户类型']
plt.barh(x,height=0.5,width=y)
plt.title('不同类型用户消费总金额对比')
for x,y in enumerate(y):
plt.text(y+30000,x,np.round(y),ha='center',va='center',fontsize=10)
plt.xticks(np.arange(0,600001,50000))
plt.tight_layout()
plt.savefig('不同类型用户消费总金额对比',dpi=300)
绘制图形如下所示:
#可视化展示:不同类型用户消费金额占比分析
plt.rcParams['font.family']=['Arial Unicode MS']
plt.figure(figsize=(8,3),dpi=100)
y=rfm2['消费占比']
x=rfm2['用户类型']
plt.barh(x,height=0.5,width=y)
plt.title('不同类型用户消费总金额对比')
for x,y in enumerate(y):
plt.text(y+0.02,x,str(y*100)[:3]+'%',ha='center',va='center',fontsize=10)
plt.xticks(np.arange(0,0.7,0.1))
plt.tight_layout()
plt.savefig('不同类型用户消费金额占比对比',dpi=300)
绘制图形如下:
由上述图形可知:
重要价值客户人数占比虽小,仅为 15%,但其创造的经济价值却是最高的,占当月总收入的 45%;故针对这类用户的营销其实是最有效且最高效的。
但我们光对比两张图无法得出明显的结论,下面绘制各用户群人均消费金额图表。
3、不同用户类型人均消费金额情况:
先添加【平均消费金额】字段:
rfm2=pd.merge(count,mon,left_on='用户类型',right_on='用户类型',how='inner')
rfm2['平均消费金额']=rfm2['消费总金额']/rfm2['人数']
获取数据表如下:
进行图形绘制:
#可视化展示:不同类型用户平均消费金额分析
plt.rcParams['font.family']=['Arial Unicode MS']
plt.figure(figsize=(8,3),dpi=100)
y=rfm2['平均消费金额']
x=rfm2['用户类型']
plt.barh(x,height=0.5,width=y)
plt.title('不同类型用户消费总金额对比')
for x,y in enumerate(y):
plt.text(y+10,x,np.round(y),ha='center',va='center',fontsize=10)
plt.xticks(np.arange(0,400,50))
plt.tight_layout()
plt.savefig('不同类型用户平均消费金额对比',dpi=300)
图形绘制如下:
在此我们可以直观地看到,重要价值客户的人均贡献金额达到了 318 元,在所有客户群中是最为突出的,针对该类用户的营销策略也应着重进行。
五、结语
其实上述建模只是企业用户分层中最为基础的一种,一般来说由于企业数据库的存在,上述用户分类会大大简化。除了上述的 RFM 三个指标,还会涉及到其他方方面面,以满足企业运行中的精细化策略运营。
以作者所在的线上出行行业为例,一般的分类标签有:下单、上线、撤单、优惠券包购买、充值、目的地(如机场、火车站等)、打车里程,以这些用户行为,衍生指标+周期(一般为 7 天\15 天\30天\60天)+设定数值这样的精细化用户标签,如 7 天内打车 3 次的用户\15天内充值 100 元以上的用户等等。
觉的有用的朋友,欢迎转发哦~