背景
rfm(recency frequency monetary)模型是衡量客户价值和客户创利能力的重要工具和手段。在众多的客户关系管理(crm)的分析模式中,rfm模型是被广泛提到的。
rfm模型是属于业务分析方法与模型中的部分。它的本质是用户分类。本文将用现代最流行的编程语言---python语言来实践课堂上讲解的rfm模型,将用户进行分类。
本文采用anaconda进行python编译,主要涉及的python模块:
pandas
matplotlib
seaborn
datetime
本章分为三部分讲解:
1.rfm模型原理与步骤
2.python分布实现rfm
3.总结
rfm模型原理与步骤
rfm模型的思路是:该模型是根据用户历史行为数据,结合业务理解选择划分维度,实现用户分类,助力用户精准营销。此外,还学习了构建rfm模型的步骤:
获取r、f、m三个维度下的原始数据
定义r、f、m的评估模型与判断阈值
进行数据处理,获取r、f、m的值
参照评估模型与阈值,对用户进行分层
针对不同层级用户制定运营策略
上面步骤可以知道,我们需要有rfm三个维度,根据我们在业务分析方法课程中学到的,业务分析模型离不开指标,而指标是对度量的汇总。因此,在找出rfm三个维度后,需要对每个维度下度量实现不同汇总规则。下面讲述对r、f、m三个维度下的度量如何进行汇总。
1.r代表最近一次消费,是计算最近一次消费时间点和当前时间点的时间差。因此,这里需要用到多维数据透视分析中的基本透视规则---最小值min求出最小的时间差。
2.f代表消费频次,是在指定区间内统计用户的购买次数。因此,这里需要用到多维数据透视分析中的基本透视规则---技术类count(技术类不去重指标)统计用户的购买次数。
3.m代表消费金额,是指在指定区间内统计用户的消费总金额,因此,这里需要用到求和类指标,也即基本透视规则中的合计规则---sum。
在对得到rfm模型中的指标值后最重要的一步就是分层,根据我们在课堂上学到的内容,大部分的用户分层是根据经验来分层的,本文在追求数据的客观性下采取统计学中的等距分箱方法来进行分层,对r、f、m三个维度分成两类。
综上,我们大致了解了如何构建rfm模型,下面以python实现rfm模型,并对每一步进行详细的讲解。
03 python实现rfm模型
数据准备
本文所需的数据是一家公司对2021年10月底至今的客户购买行为数据,(前十二行)如图下:
其中,uid代表客户的id,是存在重复情况的。prince维度代表客户每发生一次交易行为所花费的金额。time为客户发生交易行为的时间。
数据读取与理解
在得到一份数据之后,我们第一步就是要理解数据的业务意义,以及对数据表的eda(探索性分析),这里通过如下代码,发现以下特征:
具体代码(包含python导入包部分)如下:
# 导入相关包import pandas as pdimport timeimport numpy as npimport seaborn as snsimport matplotlib.pyplot as pltplt.rcparams['font.sans-serif'] = [simhei]plt.rcparams[axes.unicode_minus] = falsesns.set(style=darkgrid)# 数据读取与查看data = pd.read_excel('data.xlsx')data.head()data.isnull().sum() #查看缺失值data.duplicated().sum() #重复值,但是不删data.dtypes #查看数据类型data.describe()# 创建dataframe,存放rfm各值data_rfm = pd.dataframe()
接下来进行r、f、m指标值构建。
时间维度处理
从上文可以知道time维度,即每笔交易行为发生的时间是字符串object的格式,而在python中我们对时间作差需要的是datetime格式,因此利用pandas库中的pd.to_datetime函数将时间格式进行转换,代码如下:
data['time'] = pd.to_datetime(data['time'])
得到的前五行数据如图下,可以看到数据类型变成了datetime64[ns]
统计每笔订单产生时间与当前时间的差(这里的当前时间是2021年12月11日),得到的差是timedelta64[ns]类型
可以看到时间差中包含了day、时、分、秒4个维度,但是这里我们仅需要day维度,因此我们用astype()函数将类型转为仅含有day维度的timedelta64[d]类型。具体代码如下:
# 统计没条数据与当前日期的时间差## 计算相差天数data['r'] = (pd.datetime.now() - data['time'])## 将时间差timedelta格式转化为需要的日格式data['r'] = data['r'].astype('timedelta64[d]').astype('int')
(tips:这里可能会报警告:futurewarning: the pandas.datetime class is deprecated and will be removed from pandas in a future version. import from datetime module instead.读者无需理会,这是由于我们所用的pd.datetime.now()是一个比较旧的函数,以后将会废弃。)
统计r值
在上面我们已经创建了名为data_rfm的表结构的数据框,因此,将下面统计的r值放入其中。r值得统计是找客户最近发生交易行为日期与当前日期的差。换一种思路就是找所有时间差中的最小值。
因此利用pandas中的groupby函数对每个用户以上一步统计的r值作为分组依据进行分组,并求出最小值。具体代码如下:
data_rfm = pd.merge(data_rfm,data.groupby('uid')['r'].min(), left_on = 'user_id',right_on='uid')
统计f值
f值得统计就是统计指定区间内的消费频次,而指定区间一般为人为设定,这里我们取全部数据,即2021年10月底至今作为指定区间。
本文利用value_counts()函数对uid进行统计即为每个用户得消费频次,同时将结果合并到data_rfm数据框中。
# 统计指定区间内的消费频次data_rfm['user_id'] = data['uid'].value_counts().indexdata_rfm['f'] = data['uid'].value_counts().values
统计m值
本文以uid作为分组依据对price字段进行求和,得到求和类指标m值。此外,将结果合并到data_rfm数据框中。
data_rfm = pd.merge(data_rfm,data.groupby('uid')['price'].sum(), left_on = 'user_id',right_on='uid')data_rfm.rename(columns={'price':'m'},inplace = true)
上述代码中出现了pandas库中得合并语法merge(),merge()函数采取的是横向合并,不同于mysql,不需要指定左表还是右表为主表,只需要提供左表与右表的公共字段在各表中的名称即可。
由于data_rfm数据表中的user_id是去重的,因此将其作为主键。而data.groupby('uid')['price'].sum()得到的表格也是去重的,因此我们可以采取多维数据模型中的连接对应关系---一对一对两表进行合并。公共字段为:左表的uid,右表的user_id。
最终表格结果如下,展现前18行:
数据分箱
在得到r、f、m三个指标值后,我们需要对这三个指标进行分类,并将每个用户进行分层。
本文不采取人为主观性的经验法则划分,而是采取等距分箱的方式划分,等距分箱的原理较简单,这里写出步骤:
从最小值到最大值之间,均分为$n$等份(这里$n$取为2)。
如果 $a$,$b$ 为最小最大值, 则每个区间的长度为 $w=(b−a)/n$ ,.
则区间边界值为$a+w$,$a+2w$,….$a+(n−1)w$ 。这里只考虑边界,采用左闭右开的方式,即每个等份的实例数量不等。
在python中可以利用pandas库中的cut()函数轻松实现上述等距分箱,同时将结果r_label,f_label,m_label合并到data_rfm数据框中具体代码如下:
# 分箱 客观 左闭右开cut_r = pd.cut(data_rfm['r'],bins = 2,right = false,labels = range(1,3)).astype('int')data_rfm['r_label'] = cut_rcut_f = pd.cut(data_rfm['f'],bins = 2,right = false,labels = range(1,3)).astype('int')data_rfm['f_label'] = cut_fcut_m = pd.cut(data_rfm['m'],bins = 2,right = false,labels = range(1,3)).astype('int')data_rfm['m_label'] = cut_m
由于利用cut()函数得到的是区间形式的值,因此需要赋予label值进行虚拟变量引用。label值使用1和2,对应的区间为从小到大。具体代表意思如下表:
得到最终的表格形式如下:
用户分类
在得到每个用户的r、f、m三个维度的label值后,最后就是需要对用户进行分类,分类的原则如图下:
利用pandas库中的·terrows()函数循环遍历每个用户行为记录,将符合上述条件的划分对应的类,具体代码如下:
for i,j in data_rfm.iterrows(): if j['r_label'] == 2 and j['f_label'] == 2 and j['m_label'] == 2: data_rfm.loc[i,'用户类别'] = '重要价值用户' if j['r_label'] == 2 and j['f_label'] == 1 and j['m_label'] == 2: data_rfm.loc[i,'用户类别'] = '重要发展用户' if j['r_label'] == 1 and j['f_label'] == 2 and j['m_label'] == 2: data_rfm.loc[i,'用户类别'] = '重要保持用户' if j['r_label'] == 1 and j['f_label'] == 1 and j['m_label'] == 2: data_rfm.loc[i,'用户类别'] = '重要挽留用户' if j['r_label'] == 2 and j['f_label'] == 2 and j['m_label'] == 1: data_rfm.loc[i,'用户类别'] = '一般价值用户' if j['r_label'] == 2 and j['f_label'] == 1 and j['m_label'] == 1: data_rfm.loc[i,'用户类别'] = '一般发展用户' if j['r_label'] == 1 and j['f_label'] == 2 and j['m_label'] == 1: data_rfm.loc[i,'用户类别'] = '一般保持用户' if j['r_label'] == 1 and j['f_label'] == 1 and j['m_label'] == 1: data_rfm.loc[i,'用户类别'] = '一般挽留用户'
条形图可视化用户类别
利用seaborn画图库对已划分类别的用户进行技术统计与可视化,得到如下图表
可以看出,大部分的用户属于一般发展用户与一般挽留用户。而对于一般发展用户而言采取的策略为挖掘需求,后者则是放弃治疗。因此,可以看出该公司在10月底至今的时间段内,用户流失较多,但是可发展的用户同样是非常多的,想要提高收入,对一般发展用户入手是成本少,效率高的选择。
总结
rfm模型同时还利用了多维数据透视分析和业务分析方法两个模块的内容。所以说实践是检验和巩固学到的东西的最好方法。
例如一级的常考题上,我们常碰到一个模拟题,包含rfm模型划分规则和一张帕累托图,问题是在公司有限成本下提高公司收入,需要针对哪种用户营销最好,答案是一般发展用户。相信大家一开始都很疑惑为什么选这个,这时候如果像本文一样对一份数据进行实践,这样你就会更加理解为什么是这个答案。
声光报替、无线信号发射和接收电路设计
中小企业搭建网站选择虚拟主机还是云服务器?华为云有话说
传感器上《新闻联播》了!被列为10大科技之首,重要性堪比芯片
苹果亚马逊等产品难以维修,加剧电子垃圾的产生
所托瑞安智能防碰撞系统荣获商用车ADAS技术领先奖
基于Python语言的RFM模型讲解
满足分析型用户需求!超大束流,超快分析的场发射扫描电镜SEM4000 来了
三大前辈教你怎么学好模拟电路
美中贸易战火持续升温 国内半导体采购战略转向欧洲
私人订制Linux的全部操作,打造一个属于自己的Linux小系统
乾照砷化镓太阳电池可用于航天领域
半导体芯片推拉力测试机综合分析:特点、应用和优势
呼吸机中的主要传感器包括哪些
消费级机器人产品逐渐走入消费者视野,创造了改变生活方式的新手段
RC正弦波发生器及波形变换
四款华为新设备代号曝光 均搭载麒麟980
如何处理适用于鳄鱼夹/钩的同轴电缆
讯维平板无纸化会议系统方案解析
AI如何完成人类无法做到的设计
!销售/收购 R3271 R3273 R9211E 频谱分