欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

基于RFM 模型的 Python 实战分析

程序员文章站 2024-01-21 12:46:04
...

基于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

基于RFM 模型的 Python 实战分析
由于本次数据只需提取已完成的订单,故对【订单状态】查看其状态:

a=df.groupby('订单状态')['订单编号'].count().reset_index()

基于RFM 模型的 Python 实战分析

3.提取有用字段

由上可知:数据表中订单存在3种类型状态,订单未支付、订单支付未评价、订单已支付已评价。

上述 3 种订单均为已完成的订单,故无需对订单状态字段进行处理。

RFM模型中仅需 乘客编号,订单时间,订单金额,故将数据字段进行精简,仅保留以上 3 个字段。

df=df[['乘客编号','订单金额','叫车时间']]
df.head()

基于RFM 模型的 Python 实战分析

4.数据清洗

运行后发现叫车时间存在转义符,需对其进行处理:

(此处即对叫车时间进行切片,丢弃其最后两个字符)

df['叫车时间']=df['叫车时间'].apply(lambda x: x[:-2])
df.head()

基于RFM 模型的 Python 实战分析

查看数据类型,看是否有丢失或残缺:

df.info()

基于RFM 模型的 Python 实战分析
各字段数据完整,均为 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 模型的 Python 实战分析

三、RFM 模型建立:

基础清洗告一段落,这一步关键在于构建模型所需的三个字段:

R(最近一次购买距今多少天);
F(购买了多少次);
M(平均或者累计购买金额);

下面开始构造上述三个相关的衡量指标,即最近一次购买距今的天数差R、消费频率F、消费金额M及创建新表RFM。

1、 R 字段的构造:

先求出每位乘客的最近一次叫车时间:

r=df.groupby('乘客编号')['叫车时间'].max().reset_index()
#获得每一位乘客的最近一次叫车时间
r.loc[:10]

基于RFM 模型的 Python 实战分析
再以获取数据的时间(2020/3/1)减去叫车时间,即为R:

r['R']=(pd.to_datetime('2020-3-1')-r['叫车时间']).dt.days
r=r[['乘客编号','R']]
r.loc[:10]   

基于RFM 模型的 Python 实战分析

2、F 字段的构造

由于叫车时间为年月日时分秒的格式,故我们要先获得一个日期标签:

df['日期标签']=df['叫车时间'].astype(str).str[:10]
df.head()

基于RFM 模型的 Python 实战分析
一般建立 RFM 模型时,我们会将客户一天内的多笔订单视为一笔

即将以乘客编号&日期标签作聚合,获得各个乘客在 每一天的打车频次:

df_1=df.groupby(['乘客编号','日期标签'])['叫车时间'].count().reset_index()
df_1.loc[:10]

基于RFM 模型的 Python 实战分析

再以乘客编号作聚合,获得乘客在 2 月当月的打车天数:

f=df_1.groupby('乘客编号')['日期标签'].count().reset_index()
f.columns=['乘客编号','F']
f.head()

基于RFM 模型的 Python 实战分析

3、M 字段的构造:

M(每日平均下单金额)= 乘客总下单金额 / F(购买频次)

先求乘客总下单金额:

sum_m=df.groupby('乘客编号')['订单金额'].sum().reset_index()
sum_m.columns=['乘客编号','2月总支付金额']
sum_m.head()

基于RFM 模型的 Python 实战分析

以乘客编号为依据对频次表和总金额表进行表连接:

sum_to_f=pd.merge(sum_m,f,left_on='乘客编号',right_on='乘客编号',how='inner')
sum_to_f.head()

基于RFM 模型的 Python 实战分析
计算用户平均每天的打车金额:

sum_to_f['M']=sum_to_f['2月总支付金额']/sum_to_f['F']
sum_to_f.head()

基于RFM 模型的 Python 实战分析

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()

基于RFM 模型的 Python 实战分析

5、维度打分:

经过上面的处理,我们已经获得每个乘客的R\F\M 值,但由于他们各自之间数值的差距仍旧较大,所以我们下一步要对上述 RFM 数值进行维度打分,一般情况下分为 1分-5 分;

在我们不知道怎么去获取维度指标,也就是数据分组时,可以先看下 RFM 的描述性统计量:

rfm.describe()

基于RFM 模型的 Python 实战分析

由上可知:

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 获得了相应的维度打分;
基于RFM 模型的 Python 实战分析

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

运行结果如下:
基于RFM 模型的 Python 实战分析
将三项评价标准串联,获取人群数值打分项:

人群数值=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)     

运行结果如下:
基于RFM 模型的 Python 实战分析

至此,我们就完成了数据建模,每个用户都获得其相应的用户标签。

四、数据可视化

1、各用户群人数&占比分析:

以人群类型进行聚合:

count=rfm['人群类型'].value_counts().reset_index()
count.columns=['用户类型','人数']
count['人数占比']=count['人数']/count['人数'].sum()

获得 count 数据表如下:
基于RFM 模型的 Python 实战分析

可视化展示:不同类型用户人数分析

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)

绘制图形如下:

基于RFM 模型的 Python 实战分析

#可视化展示:不同类型用户人数占比分析
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)

绘制图形如下:
基于RFM 模型的 Python 实战分析

由上图可知,所有用户类型中:

高消费挽回类客户人数最多,占比 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 如下所示:
基于RFM 模型的 Python 实战分析

绘制用户类型与消费总金额或消费占比的图表:

#可视化展示:不同类型用户消费总金额分析
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)

绘制图形如下所示:
基于RFM 模型的 Python 实战分析

#可视化展示:不同类型用户消费金额占比分析
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)

绘制图形如下:
基于RFM 模型的 Python 实战分析

由上述图形可知:

重要价值客户人数占比虽小,仅为 15%,但其创造的经济价值却是最高的,占当月总收入的 45%;故针对这类用户的营销其实是最有效且最高效的。

但我们光对比两张图无法得出明显的结论,下面绘制各用户群人均消费金额图表

3、不同用户类型人均消费金额情况:

先添加【平均消费金额】字段:

rfm2=pd.merge(count,mon,left_on='用户类型',right_on='用户类型',how='inner')
rfm2['平均消费金额']=rfm2['消费总金额']/rfm2['人数']

获取数据表如下:
基于RFM 模型的 Python 实战分析
进行图形绘制:

#可视化展示:不同类型用户平均消费金额分析
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)

图形绘制如下:
基于RFM 模型的 Python 实战分析

在此我们可以直观地看到,重要价值客户的人均贡献金额达到了 318 元,在所有客户群中是最为突出的,针对该类用户的营销策略也应着重进行。

五、结语

    其实上述建模只是企业用户分层中最为基础的一种,一般来说由于企业数据库的存在,上述用户分类会大大简化。除了上述的 RFM 三个指标,还会涉及到其他方方面面,以满足企业运行中的精细化策略运营。

    以作者所在的线上出行行业为例,一般的分类标签有:下单、上线、撤单、优惠券包购买、充值、目的地(如机场、火车站等)、打车里程,以这些用户行为,衍生指标+周期(一般为 7 天\15 天\30天\60天)+设定数值这样的精细化用户标签,如 7 天内打车 3 次的用户\15天内充值 100 元以上的用户等等。

   觉的有用的朋友,欢迎转发哦~