模型介绍
RFM模型即"R"——Recency(最近一次消费时间)、“F”——Frequency(一段时间内消费频次)、“M”——(一段时间内消费总额)。这三个指标可以将我们的用户划分成不同的等级和层次,目的是为了衡量他们的用户价值,从而能够更准确地将成本和精力花在更精确的用户层次身上。一个典型的例子就是针对一个明显无意愿的流失用户,对其继续push自己的核心产品,费时费力也费钱。
数据清洗
import pandas as pd
import numpy as np
import os
df = pd.read_excel('PYTHON-RFM实战数据.xlsx')
df.head()
|
品牌名称
|
买家昵称
|
付款日期
|
订单状态
|
实付金额
|
邮费
|
省份
|
城市
|
购买数量
|
0
|
数据不吹牛
|
叫我李2
|
2019-01-01 00:17:59
|
交易成功
|
186
|
6
|
上海
|
上海市
|
1
|
1
|
数据不吹牛
|
0cyb1992
|
2019-01-01 00:59:54
|
交易成功
|
145
|
0
|
广东省
|
广州市
|
1
|
2
|
数据不吹牛
|
萝污萌莉
|
2019-01-01 07:48:48
|
交易成功
|
194
|
8
|
山东省
|
东营市
|
1
|
3
|
数据不吹牛
|
atblovemyy
|
2019-01-01 09:15:49
|
付款以后用户退款成功,交易自动关闭
|
84
|
0
|
江苏省
|
镇江市
|
1
|
4
|
数据不吹牛
|
小星期鱼
|
2019-01-01 09:59:33
|
付款以后用户退款成功,交易自动关闭
|
74
|
0
|
上海
|
上海市
|
1
|
df['订单状态'].unique()
array(['交易成功', '付款以后用户退款成功,交易自动关闭'], dtype=object)
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 28833 entries, 0 to 28832
Data columns (total 9 columns):# Column Non-Null Count Dtype
--- ------ -------------- ----- 0 品牌名称 28833 non-null object 1 买家昵称 28833 non-null object 2 付款日期 28833 non-null datetime64[ns]3 订单状态 28833 non-null object 4 实付金额 28833 non-null int64 5 邮费 28833 non-null int64 6 省份 28833 non-null object 7 城市 28832 non-null object 8 购买数量 28833 non-null int64
dtypes: datetime64[ns](1), int64(3), object(5)
memory usage: 2.0+ MB
df = df.loc[df['订单状态'] == '交易成功',:]
print('剔除退款后还剩:%d行' % len(df))
剔除退款后还剩:27793行
df = df[['买家昵称','付款日期','实付金额']]
df.head()
|
买家昵称
|
付款日期
|
实付金额
|
0
|
叫我李2
|
2019-01-01 00:17:59
|
186
|
1
|
0cyb1992
|
2019-01-01 00:59:54
|
145
|
2
|
萝污萌莉
|
2019-01-01 07:48:48
|
194
|
5
|
重碎叠
|
2019-01-01 10:00:07
|
197
|
6
|
iho_jann
|
2019-01-01 10:00:08
|
168
|
R值构造
r = df.groupby('买家昵称')['付款日期'].max().reset_index()
r.head()
|
买家昵称
|
付款日期
|
0
|
.blue_ram
|
2019-02-04 17:49:34.000
|
1
|
.christiny
|
2019-01-29 14:17:15.000
|
2
|
.willn1
|
2019-01-11 03:46:18.000
|
3
|
.托托m
|
2019-01-11 02:26:33.000
|
4
|
0000妮
|
2019-06-28 16:53:26.458
|
r['R'] = (pd.to_datetime('2019-7-1') - r['付款日期']).dt.days
r = r[['买家昵称','R']]
r.head()
|
买家昵称
|
R
|
0
|
.blue_ram
|
146
|
1
|
.christiny
|
152
|
2
|
.willn1
|
170
|
3
|
.托托m
|
170
|
4
|
0000妮
|
2
|
F值构造
#引入日期标签辅助列
df['日期标签'] = df['付款日期'].astype(str).str[:10]
#把单个用户一天内订单合并
dup_f = df.groupby(['买家昵称','日期标签'])['付款日期'].count().reset_index()
#对合并后的用户统计频次
f = dup_f.groupby('买家昵称')['付款日期'].count().reset_index()
f.columns = ['买家昵称','F']
f.head()
|
买家昵称
|
F
|
0
|
.blue_ram
|
1
|
1
|
.christiny
|
1
|
2
|
.willn1
|
1
|
3
|
.托托m
|
1
|
4
|
0000妮
|
1
|
M值构造
sum_m = df.groupby('买家昵称')['实付金额'].sum().reset_index()
sum_m.columns = ['买家昵称','总支付金额']
com_m = pd.merge(sum_m,f,left_on = '买家昵称',right_on = '买家昵称',how = 'inner')
#计算用户平均支付金额
com_m['M'] = com_m['总支付金额'] / com_m['F']
com_m.head()
|
买家昵称
|
总支付金额
|
F
|
M
|
0
|
.blue_ram
|
49
|
1
|
49.0
|
1
|
.christiny
|
183
|
1
|
183.0
|
2
|
.willn1
|
34
|
1
|
34.0
|
3
|
.托托m
|
37
|
1
|
37.0
|
4
|
0000妮
|
164
|
1
|
164.0
|
rfm = pd.merge(r,com_m,left_on = '买家昵称',right_on = '买家昵称',how = 'inner')
rfm = rfm[['买家昵称','R','F','M']]
rfm.head()
|
买家昵称
|
R
|
F
|
M
|
0
|
.blue_ram
|
146
|
1
|
49.0
|
1
|
.christiny
|
152
|
1
|
183.0
|
2
|
.willn1
|
170
|
1
|
34.0
|
3
|
.托托m
|
170
|
1
|
37.0
|
4
|
0000妮
|
2
|
1
|
164.0
|
STEP 3.维度确认(不涉及代码故省略)
STEP 4.分值计算
rfm['R-SCORE'] = pd.cut(rfm['R'],bins = [0,30,60,90,120,1000000],labels = [5,4,3,2,1],right = False).astype(float)
rfm.head()
|
买家昵称
|
R
|
F
|
M
|
R-SCORE
|
0
|
.blue_ram
|
146
|
1
|
49.0
|
1.0
|
1
|
.christiny
|
152
|
1
|
183.0
|
1.0
|
2
|
.willn1
|
170
|
1
|
34.0
|
1.0
|
3
|
.托托m
|
170
|
1
|
37.0
|
1.0
|
4
|
0000妮
|
2
|
1
|
164.0
|
5.0
|
F、M值计算
rfm['F-SCORE'] = pd.cut(rfm['F'],bins = [1,2,3,4,5,1000000],labels = [1,2,3,4,5],right = False).astype(float)
rfm['M-SCORE'] = pd.cut(rfm['M'],bins = [0,50,100,150,200,1000000],labels = [1,2,3,4,5],right = False).astype(float)
rfm.head()
|
买家昵称
|
R
|
F
|
M
|
R-SCORE
|
F-SCORE
|
M-SCORE
|
0
|
.blue_ram
|
146
|
1
|
49.0
|
1.0
|
1.0
|
1.0
|
1
|
.christiny
|
152
|
1
|
183.0
|
1.0
|
1.0
|
4.0
|
2
|
.willn1
|
170
|
1
|
34.0
|
1.0
|
1.0
|
1.0
|
3
|
.托托m
|
170
|
1
|
37.0
|
1.0
|
1.0
|
1.0
|
4
|
0000妮
|
2
|
1
|
164.0
|
5.0
|
1.0
|
4.0
|
#和平均值对比,减少客户分类数量
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.head()
|
买家昵称
|
R
|
F
|
M
|
R-SCORE
|
F-SCORE
|
M-SCORE
|
R是否大于均值
|
F是否大于均值
|
M是否大于均值
|
0
|
.blue_ram
|
146
|
1
|
49.0
|
1.0
|
1.0
|
1.0
|
0
|
0
|
0
|
1
|
.christiny
|
152
|
1
|
183.0
|
1.0
|
1.0
|
4.0
|
0
|
0
|
1
|
2
|
.willn1
|
170
|
1
|
34.0
|
1.0
|
1.0
|
1.0
|
0
|
0
|
0
|
3
|
.托托m
|
170
|
1
|
37.0
|
1.0
|
1.0
|
1.0
|
0
|
0
|
0
|
4
|
0000妮
|
2
|
1
|
164.0
|
5.0
|
1.0
|
4.0
|
1
|
0
|
1
|
STEP 5.客户分层
构建合并指标
rfm['人群数值'] = (rfm['R是否大于均值'] * 100) + (rfm['F是否大于均值'] * 10) + (rfm['M是否大于均值'] * 1)
rfm.head()
|
买家昵称
|
R
|
F
|
M
|
R-SCORE
|
F-SCORE
|
M-SCORE
|
R是否大于均值
|
F是否大于均值
|
M是否大于均值
|
人群数值
|
0
|
.blue_ram
|
146
|
1
|
49.0
|
1.0
|
1.0
|
1.0
|
0
|
0
|
0
|
0
|
1
|
.christiny
|
152
|
1
|
183.0
|
1.0
|
1.0
|
4.0
|
0
|
0
|
1
|
1
|
2
|
.willn1
|
170
|
1
|
34.0
|
1.0
|
1.0
|
1.0
|
0
|
0
|
0
|
0
|
3
|
.托托m
|
170
|
1
|
37.0
|
1.0
|
1.0
|
1.0
|
0
|
0
|
0
|
0
|
4
|
0000妮
|
2
|
1
|
164.0
|
5.0
|
1.0
|
4.0
|
1
|
0
|
1
|
101
|
def transform_label(x):if x == 111:label = '重要价值客户'elif x == 110:label = '消费潜力客户'elif x == 101:label = '频次深耕客户'elif x == 100:label = '新客户'elif x == 11:label = '重要价值流失预警客户'elif x == 10:label = '一般客户'elif x == 1:label = '高消费唤回客户'elif x == 0:label = '流失客户'return label
rfm['人群类型'] = rfm['人群数值'].apply(transform_label)
rfm.head()
|
买家昵称
|
R
|
F
|
M
|
R-SCORE
|
F-SCORE
|
M-SCORE
|
R是否大于均值
|
F是否大于均值
|
M是否大于均值
|
人群数值
|
人群类型
|
0
|
.blue_ram
|
146
|
1
|
49.0
|
1.0
|
1.0
|
1.0
|
0
|
0
|
0
|
0
|
流失客户
|
1
|
.christiny
|
152
|
1
|
183.0
|
1.0
|
1.0
|
4.0
|
0
|
0
|
1
|
1
|
高消费唤回客户
|
2
|
.willn1
|
170
|
1
|
34.0
|
1.0
|
1.0
|
1.0
|
0
|
0
|
0
|
0
|
流失客户
|
3
|
.托托m
|
170
|
1
|
37.0
|
1.0
|
1.0
|
1.0
|
0
|
0
|
0
|
0
|
流失客户
|
4
|
0000妮
|
2
|
1
|
164.0
|
5.0
|
1.0
|
4.0
|
1
|
0
|
1
|
101
|
频次深耕客户
|
人数统计
count = rfm['人群类型'].value_counts().reset_index()
count.columns = ['客户类型','人数']
count['人数占比'] = count['人数'] / count['人数'].sum()
count
|
客户类型
|
人数
|
人数占比
|
0
|
高消费唤回客户
|
7338
|
0.288670
|
1
|
流失客户
|
6680
|
0.262785
|
2
|
频次深耕客户
|
5427
|
0.213493
|
3
|
新客户
|
4224
|
0.166168
|
4
|
重要价值客户
|
756
|
0.029740
|
5
|
消费潜力客户
|
450
|
0.017703
|
6
|
重要价值流失预警客户
|
360
|
0.014162
|
7
|
一般客户
|
185
|
0.007278
|
金额统计
rfm['购买总金额'] = rfm['F'] * rfm['M']
mon = rfm.groupby('人群类型')['购买总金额'].sum().reset_index()
mon.columns = ['客户类型','消费金额']
mon['金额占比'] = mon['消费金额'] / mon['消费金额'].sum()
mon
|
客户类型
|
消费金额
|
金额占比
|
0
|
一般客户
|
25803.0
|
0.007349
|
1
|
新客户
|
270869.0
|
0.077142
|
2
|
流失客户
|
444617.0
|
0.126624
|
3
|
消费潜力客户
|
64075.0
|
0.018248
|
4
|
重要价值客户
|
269230.0
|
0.076675
|
5
|
重要价值流失预警客户
|
116665.0
|
0.033226
|
6
|
频次深耕客户
|
981893.0
|
0.279638
|
7
|
高消费唤回客户
|
1338153.0
|
0.381098
|
#输入源数据文件名
def get_rfm(name = 'PYTHON-RFM实战数据.xlsx'):df = pd.read_excel(name)df = df.loc[df['订单状态'] == '交易成功',:]print('剔除退款后还剩:%d行' % len(df))df = df[['买家昵称','付款日期','实付金额']]r = df.groupby('买家昵称')['付款日期'].max().reset_index()r['R'] = (pd.to_datetime('2019-7-1') - r['付款日期']).dt.daysr = r[['买家昵称','R']]#引入日期标签辅助列df['日期标签'] = df['付款日期'].astype(str).str[:10]#把单个用户一天内订单合并dup_f = df.groupby(['买家昵称','日期标签'])['付款日期'].count().reset_index()#对合并后的用户统计频次f = dup_f.groupby('买家昵称')['付款日期'].count().reset_index()f.columns = ['买家昵称','F']sum_m = df.groupby('买家昵称')['实付金额'].sum().reset_index()sum_m.columns = ['买家昵称','总支付金额']com_m = pd.merge(sum_m,f,left_on = '买家昵称',right_on = '买家昵称',how = 'inner')#计算用户平均支付金额com_m['M'] = com_m['总支付金额'] / com_m['F']rfm = pd.merge(r,com_m,left_on = '买家昵称',right_on = '买家昵称',how = 'inner')rfm = rfm[['买家昵称','R','F','M']]rfm['R-SCORE'] = pd.cut(rfm['R'],bins = [0,30,60,90,120,1000000],labels = [5,4,3,2,1],right = False).astype(float)rfm['F-SCORE'] = pd.cut(rfm['F'],bins = [1,2,3,4,5,1000000],labels = [1,2,3,4,5],right = False).astype(float)rfm['M-SCORE'] = pd.cut(rfm['M'],bins = [0,50,100,150,200,1000000],labels = [1,2,3,4,5],right = False).astype(float)rfm['R是否大于均值'] = (rfm['R-SCORE'] > rfm['R-SCORE'].mean()) * 1rfm['F是否大于均值'] = (rfm['F-SCORE'] > rfm['F-SCORE'].mean()) * 1rfm['M是否大于均值'] = (rfm['M-SCORE'] > rfm['M-SCORE'].mean()) * 1rfm['人群数值'] = (rfm['R是否大于均值'] * 100) + (rfm['F是否大于均值'] * 10) + (rfm['M是否大于均值'] * 1)rfm['人群类型'] = rfm['人群数值'].apply(transform_label)count = rfm['人群类型'].value_counts().reset_index()count.columns = ['客户类型','人数']count['人数占比'] = count['人数'] / count['人数'].sum()rfm['购买总金额'] = rfm['F'] * rfm['M']mon = rfm.groupby('人群类型')['购买总金额'].sum().reset_index()mon.columns = ['客户类型','消费金额']mon['金额占比'] = mon['消费金额'] / mon['消费金额'].sum()result = pd.merge(count,mon,left_on = '客户类型',right_on = '客户类型')return result#判断R/F/M是否大于均值
def transform_label(x):if x == 111:label = '重要价值客户'elif x == 110:label = '消费潜力客户'elif x == 101:label = '频次深耕客户'elif x == 100:label = '新客户'elif x == 11:label = '重要价值流失预警客户'elif x == 10:label = '一般客户'elif x == 1:label = '高消费唤回客户'elif x == 0:label = '流失客户'return label
res = get_rfm(name = 'PYTHON-RFM实战数据.xlsx')
res
剔除退款后还剩:27793行
|
客户类型
|
人数
|
人数占比
|
消费金额
|
金额占比
|
0
|
高消费唤回客户
|
7338
|
0.288670
|
1338153.0
|
0.381098
|
1
|
流失客户
|
6680
|
0.262785
|
444617.0
|
0.126624
|
2
|
频次深耕客户
|
5427
|
0.213493
|
981893.0
|
0.279638
|
3
|
新客户
|
4224
|
0.166168
|
270869.0
|
0.077142
|
4
|
重要价值客户
|
756
|
0.029740
|
269230.0
|
0.076675
|
5
|
消费潜力客户
|
450
|
0.017703
|
64075.0
|
0.018248
|
6
|
重要价值流失预警客户
|
360
|
0.014162
|
116665.0
|
0.033226
|
7
|
一般客户
|
185
|
0.007278
|
25803.0
|
0.007349
|
Python实现RFM模型相关推荐
- python给用户打标签_用Python实现RFM模型——互联网产品用户分层必备技巧
1.前言 RFM模型即"R"--Recency(最近一次消费时间)."F"--Frequency(一段时间内消费频次)."M"--(一段时间 ...
- 【Python】RFM模型实现
[Python]RFM模型实现 1 RFM模型 RFM模型:根据用户历史行为数据,结合业务理解,实现用户分层分类,助力用户的精准营销,是衡量客户价值和客户创利能力的重要工具和手段 Recency 最近 ...
- Python数据挖掘-RFM模型K-means聚类分析-航空公司客户价值分析
使用教材:<Python数据分析与挖掘实战> 模型:RFM模型 算法:K-means聚类:其他方法还用到了层次聚类 数据:需要数据的可以评论里call. 内容: (1)案例: 航空公司客户 ...
- Python 实现 RFM 模型(详):用户行为分析模型,商业实践与数据分析实战(含可视化)
- 基于客观事实的 RFM 模型(Python 代码)
CDA数据分析师 出品 0 1 背景 RFM(Recency Frequency Monetary)模型是衡量客户价值和客户创利能力的重要工具和手段.在众多的客户关系管理(CRM)的分析模式中,RFM ...
- RFM模型原理详解与实操运用
RFM模型原理详解与实操运用 RFM模型原理介绍 为什么要使用RFM模型 RMF模型原理介绍 RFM模型用户细分 RFM模型实例操作 背景/数据介绍 RFM模型异化构建 代码实现 最近在 运营课程中学 ...
- RFM模型的理解和python案例分析
RFM模型是什么 RFM是客户关系管理(CRM:Customer Relationship Management)中一种重要的分析模型,通过研究一个客户的交易时间.交易频率和交易总金额来衡量客户的价值 ...
- Python 某电子产品销售数据分析报告及RFM模型(一)
关注微信公共号:小程在线 关注CSDN博客:程志伟的博客 Python 3.7.6 (default, Jan 8 2020, 20:23:39) [MSC v.1916 64 bit (AMD64 ...
- python数据分析实战之用户分析及RFM模型分析
理论基础知识可以看我之前的博客: 1.python之Numpy知识点详细总结 2.python最最最重要的数据分析工具之pandas 3.pandas之表连接与高级查询 也可以进入我的专栏:欢迎订阅哦 ...
- python 估值模型_利用RFM模型建模,并通过聚类分析、分类,分别算出8中不同的价值会员...
RFM-Clustering 利用RFM模型建模,并通过聚类分析.分类,分别算出8中不同的价值会员 RFM模型构建会员价值标签 R:最近一次消费(Recency) F:消费频率(Frequency) ...
最新文章
- 综述|核心开发者全面解读Pytorch内部机制
- Oracle 11g必须开启的服务及服务详细介绍
- 学习Python一定要会的4个高阶函数
- 这样设计是否更好些~仓储接口是否应该设计成基础操作接口和扩展操作接口
- flink中的WaterMark调研和具体实例
- 笔记本长时间不用出现一片黑屏
- .NET 开源软件开发BIM工具包xBIM
- unix/linux系统中文件分为哪些类型?,到底该如何理解 Unix/Linux 的文件系统?看这篇就知道了...
- 【洛谷P1795 无穷的序列_NOI导刊2010提高(05)】模拟
- Dojo实现Tabs页报错(二)
- oracle merge
- UnityShader16:点光源和聚光灯
- js 自定义 $ 选择器
- Java并发编程实战-高屋建瓴
- 全开源微信小程序商城系统源码:基于Java+uniapp框架开发
- 阿里巴巴Java开发手册--各个版本汇总
- 嵌入式开发与单片机开发有什么区别
- DTCMS网站开发遇到的一些问题
- 23种模式——策略模式
- JDBC与JAVA程序笔记
热门文章
- 可变参数函数——以printf为例子
- JavaScript字符转Unicode,顺便说句:GitHub的Oh no页面很亮
- 《经济地理学》读书笔记
- Shell-cat url-list.txt | xargs wget -c
- server 2012 IIS 启用.NET 4.5
- WinForm软件开机自动启动详细方法
- 【综述阅读】Ad hoc网络路由相关的几篇综述
- SEO内容为王之如何创造伪原创
- 目录中带.造成文件上传验证问题
- python 自动回收机制