RFM用户分析模型的使用

785 阅读9分钟

RFM用户分析模型简介

RFM用户分析模型简单来讲,R就是Recency,,M是Monetary,具体来说:

_Recency:最近一次消费,即上一次交易距今多少天,反映的是用户是否流失;

_Frequency:消费频率,一段时间内用户的消费频率,反映的是用户的消费活跃度;

_Monetary:消费金额,一段时间内用户消费总金额,反映的是用户价值。

根据这三个维度我们可以把用户分为8种:

用户类型 最近一次消费 消费频率 消费金额 说明
重要价值用户 三项指标都很高,优质客户,重点关注
重要唤回客户 消费频率和消费金额都很高,但最近无消费,需要唤回
重要深耕客户 消费金额高,最近有消费,但消费频率低,需要深耕
重要挽留客户 消费金额高,但消费频率低,最近无消费,需要挽留
潜力客户 消费金额低,消费频率高,最近也有消费,需要挖掘
新客户 最近有消费,属于新客户,有推广价值
一般维持客户 消费频率高但消费金额低,一般维持即可
流失客户 三项指标都低,属于流失客户

对 RFM 用户分析模型来说,只要数据中有用户名、订单日期和订单金额等数据,就可以满足数据分析的基本需求了。

案例分析

读取数据表:

import pandas as pd
#从网络链接读取数据表
df=pd.read_csv('https://media-zip1.baydn.com/storage_media_zip/srfeae/bf6dc7d814c520c60e5e632d281f14a4.ba163c25251bd44b74bde1bb4af7abdc.csv')
#print(df)

调用df.info()查看数据表信息如下:

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1692 entries, 0 to 1691
Data columns (total 3 columns):
 #   Column  Non-Null Count  Dtype 
---  ------  --------------  ----- 
 0   订单日期    1692 non-null   object
 1   用户名     1692 non-null   object
 2   订单金额    1692 non-null   int64 
dtypes: int64(1), object(2)
memory usage: 39.8+ KB
None

使用df.head(5)可以查看数据表前五行记录:

 订单日期 用户名  订单金额
0  2019-01-01  杜汇    71
1  2019-01-01  钟群   157
2  2019-01-01  贺媚   163
3  2019-01-01  许菲    38
4  2019-01-01  罗姿   302

调用df.describe()让我们对订单金额大小有大致的概念,以便后续的数据处理:

               订单金额
count   1692.000000
mean     433.797281
std      895.133325
min        1.000000
25%       36.000000
50%      148.000000
75%      478.000000
max    14052.000000

整体来看,数据比较完整,不需要特别的清洗,我们只需要将订单日期转换给日期格式,以便计算最近一次消费的日期:

df['订单日期'] = pd.to_datetime(df['订单日期'])

计算RFM值

然后我们就可以调用agg()方法来一次性计算RFM的值了:

df_rfm = df.groupby('用户名').agg({
  '订单日期': lambda x: (pd.to_datetime('2019-12-31') - x.max()).days,  # 计算 R
  '用户名': lambda x: len(x),  # 计算 F
  '订单金额': lambda x: x.sum()  # 计算 M
})

agg() 方法是 pandas 中的聚合方法,可以针对多列同时进行操作。它的用法有很多,这里只介绍参数是字典的用法。我们给 agg()方法传入一个字典,字典的键是要进行操作的列名,值为一个函数。函数的参数是每一列中的数据,函数的返回值将替换原来的值。你可以将agg()方法理解为同时针对多列进行不同操作的 apply() 方法。

表格中是 2019 年的订单数据,不包含 2020 年的数据,因此在计算 R(最近一次消费)时应该用 2019-12-31 减去用户的最近一次订单日期。日期越往后越大,因此调用max()方法可以找到该用户最近一次订单日期,最终得到的天数就是 R 的值。

因为时间跨度一样,都是一年。因此F(消费频率)可以直接用每个用户的订单数量表示。 按用户名分组后,用户名的个数就是该用户的订单数,因此通过 len() 函数可以直接得到 F 的值。

最后的 M(消费金额)也很简单,分组后直接调用sum()方法求和即可得到每个用户这一年的消费金额。

然后我们再使用rename()方法来更新以下列名:

df_rfm.rename(columns={'订单日期': 'R', '用户名': 'F', '订单金额': 'M'}, inplace=True)

这样就可以得到FRM的值形成的表格,打印出来看看:

        R  F     M
用户名              
丁元    57  1  1873
丁发   180  1  4151
丁和    25  3  1109
丁妹    37  2  2271
丁学    41  5  2291
..   ... ..   ...
龙茜   131  1   267
龚以   162  1   467
龚妹   126  3   243
龚波     2  5   558
龚邦   244  1     6

FRM值打分

先用.describe()看一下FRM值的分布情况:

           R           F             M
count  693.000000  693.000000    693.000000
mean    87.341991    2.441558   1059.141414
std     81.506870    1.317338   1464.025139
min      0.000000    1.000000      1.000000
25%     28.000000    1.000000    204.000000
50%     57.000000    2.000000    606.000000
75%    118.000000    3.000000   1334.000000
max    362.000000    9.000000  14203.000000

根据数据表中的25分位、50分位和75分位来进行分值的划分,以 R 为例,将分为 0 到 29、29 到 58、58 到 119 和 119 到 363 四个区间,分别给予4,3,2,1的分值,同理,F值可以分为0到1,1到2,2到3,3到10四个区间,分别赋分值1,2,3,4的分值,M可以分为0到204,204到606,606到1334,1334到14203等四个区间,分别赋值1,2,3,4的分值。 利用apply()函数,我们分别给R、F和M值打分:

#给R值打分
def r_score(x):
  if x <= 29:
    return 4
  elif x <= 58:
    return 3
  elif x <= 119:
    return 2
  else:
    return 1

df_rfm['r_score'] = df_rfm['R'].apply(r_score)
#给F值打分
def f_score(x):
  if x<=1:
    return 1
  elif x<=2:
    return 2
  elif x<=3:
    return 3
  else:
    return 4
df_rfm[f_score]=df_rfm['F'].apply(f_score)
#给M值打分
def m_score(x):
  if x<=204:
    return 1
  elif x<=606:
    return 2
  elif x<=1334:
    return 3
  else:
    return 4

df_rfm[m_score]=df_rfm['M'].apply(m_score)


现在把打分表打印出来看看:

         R  F     M     r_score  f_score  m_score
用户名                                         
丁元    57  1  1873        3        1        4
丁发   180  1  4151        1        1        4
丁和    25  3  1109        4        3        3
丁妹    37  2  2271        3        2        4
丁学    41  5  2291        3        4        4
..   ... ..   ...      ...      ...      ...
龙茜   131  1   267        1        1        2
龚以   162  1   467        1        1        2
龚妹   126  3   243        1        3        2
龚波     2  5   558        4        4        2
龚邦   244  1     6        1        1        1

[693 rows x 6 columns]

简化RFM结果

按照RFM的分值对客户分类过于复杂,因此我们对RFM结果做进一步简化,将大于平均值定义为“高”,小于平均值定义为“低”:

df_rfm['R高低'] = df_rfm['r_score'].apply(lambda x: '高' if x > df_rfm['r_score'].mean() else '低')
df_rfm['F高低'] = df_rfm['f_score'].apply(lambda x: '高' if x > df_rfm['f_score'].mean() else '低')
df_rfm['M高低'] = df_rfm['m_score'].apply(lambda x: '高' if x > df_rfm['m_score'].mean() else '低')

为了方便打标签,我们先将 R 高低、F 高低 和 M 高低 加起来,也就是拼接成 高低高 这种字符串:

df_rfm['RFM'] = df_rfm['R高低'] + df_rfm['F高低'] + df_rfm['M高低']

最终得到表格:

        R   F     M  r_score  f_score  m_score R高低 F高低 M高低  RFM
用户名                                                          
丁元    57  1  1873        3        1        4   高   低   高  高低高
丁发   180  1  4151        1        1        4   低   低   高  低低高
丁和    25  3  1109        4        3        3   高   高   高  高高高
丁妹    37  2  2271        3        2        4   高   低   高  高低高
丁学    41  5  2291        3        4        4   高   高   高  高高高
..   ... ..   ...      ...      ...      ...  ..  ..  ..  ...
龙茜   131  1   267        1        1        2   低   低   低  低低低
龚以   162  1   467        1        1        2   低   低   低  低低低
龚妹   126  3   243        1        3        2   低   高   低  低高低
龚波     2  5   558        4        4        2   高   高   低  高高低
龚邦   244  1     6        1        1        1   低   低   低  低低低

我们直接分析 RFM 这列的字符串排列就能知道该用户是哪种类型的,加上类型标签的代码如下:

def rfm_type(x):
  if x == '高高高':
    return '重要价值用户'
  elif x == '低高高':
    return '重要唤回用户'
  elif x == '高低高':
    return '重要深耕用户'
  elif x == '低低高':
    return '重要挽留用户'
  elif x == '高高低':
    return '潜力用户'
  elif x == '高低低':
    return '新用户'
  elif x == '低高低':
    return '一般维持用户'
  elif x == '低低低':
    return '流失用户'

df_rfm['用户类型'] = df_rfm['RFM'].apply(rfm_type)

这样我们整个RFM用户分析模型就建立起来了,结果如下:

         R   F   M  r_score  f_score  m_score  R高低 F高低 M高低  RFM    用户类型
用户名                                                                  
丁元    57  1  1873        3        1        4   高   低   高  高低高  重要深耕用户
丁发   180  1  4151        1        1        4   低   低   高  低低高  重要挽留用户
丁和    25  3  1109        4        3        3   高   高   高  高高高  重要价值用户
丁妹    37  2  2271        3        2        4   高   低   高  高低高  重要深耕用户
丁学    41  5  2291        3        4        4   高   高   高  高高高  重要价值用户
..   ... ..   ...      ...      ...      ...  ..  ..  ..  ...     ...
龙茜   131  1   267        1        1        2   低   低   低  低低低    流失用户
龚以   162  1   467        1        1        2   低   低   低  低低低    流失用户
龚妹   126  3   243        1        3        2   低   高   低  低高低  一般维持用户
龚波     2  5   558        4        4        2   高   高   低  高高低    潜力用户
龚邦   244  1     6        1        1        1   低   低   低  低低低    流失用户

[693 rows x 11 columns]

RFM 模型结果分析

先用df_rfm['用户类型'].value_counts()来统计各类客户的人数:

流失用户      164
重要价值用户    138
新用户        86
重要挽留用户     75
重要深耕用户     75
重要唤回用户     57
潜力用户       56
一般维持用户     42
Name: 用户类型, dtype: int64

利用reset_index() 方法将 Series 变成了 DataFrame,我们给表格在加一列,计算出每种类型的用户的占比分别是多少。

df_count = df_rfm['用户类型'].value_counts().reset_index()
df_count.rename(columns={'index': '用户类型', '用户类型': '人数'}, inplace=True)
df_count['占比'] = df_count['人数'] / df_count['人数'].sum()  # 人数/总人数

这样可以得到更直观的模型结果:

用户类型   人数        占比
0    流失用户  164  0.236652
1  重要价值用户  138  0.199134
2     新用户   86  0.124098
3  重要挽留用户   75  0.108225
4  重要深耕用户   75  0.108225
5  重要唤回用户   57  0.082251
6    潜力用户   56  0.080808
7  一般维持用户   42  0.060606

利用数据可视化方法更直观的展示我们的模型结果:

df_count.plot(kind='bar', x='用户类型', y=['人数'])
plt.show()  # 需要提前 import matplotlib.pyplot as plt

可以获得如下图示:

可以很直观的看到,流失用户量非常大。原因可能是某些环节用户体验不好导致用户不满意,我们需要重点关注这部分用户,制定减少用户流失的方案。同时,新用户的占比也很多,要想办法将这些用户转为重要价值用户。