Python 数据处理数据挖掘(四):用户分层模型RFM

声明:本文为学习笔记,侵权删

一、RFM模型

RFM(Recency最近一次消费,Frequency消费频率,Monetary消费金额)

R用户活跃度

F用户忠诚度

M用户重要性

R,F,M都有5个评分,均为1~5分,可简单理解为0~3分均为差,4~5均为好,评分越大越好,越小越差。通过R,F,M三个维度的划分,我们可以将用户分为8种类型,根据不同类别的客户可以制定不同的销售策略。

二、R,F,M的评判标准

大多数时候,我们拿到的数据并不会直白地给出R,F,M的具体数值,更多的是一些实际的数据,我们需要通过这些数据,找到与R,F,M相关的,然后通过计算等等操作,才能得到最终的R,F,M的数值。

以下面这份数据为例(忽略第二行的######,WPS在打开CSV文件的时候的编译错误,原文就是个日期):

 这份数据中并没有直接给出R,F,M的数值或评判标准,那么我们首先就要找到决定R,F,M的相关数据。

R,最近一次购买至今间隔的时间,可以通过数据集中最后一次消费的时间和当前时间的差得出(本文中当前时间取2019.12.30)

F,订单数量

M,消费总金额

OK,我们找到了计算,R,F,M的相关数据,那么怎么把这些数据分级,分成1~5 这五个分数呢?

这个问题是主观的,在不同的情况下可能会有不同的分级标准。

我们先来看下R,F,M相关的数据的分布情况:

import pandas as pd
from datetime import datetime
from matplotlib import pyplot as plt
data = pd.read_csv(f"D:\Python Code\dataMining\消费清单.csv")
data["首单日期"] = pd.to_datetime(data["首单日期"])
data["最近一次消费"] = pd.to_datetime(data["最近一次消费"])
#假设当前的日期是2019年12月30日,计算出Recency
#计算最近一次消费到2019.12.30的时间间隔,并在data的最后一列后增加一列Recency
currentDate = datetime(2019,12,30)
data["Recency"] = currentDate - data["最近一次消费"]
#上一行如果直接获取data["Recency"],输出的格式是“xx 天”,是timedelta类型,不便于直接获取天数,因此就需要下一行代码
data["Recency"] = data["Recency"].dt.days

#对于F,M两个指标,F就是订单数量,M就是消费总金额,可以直接得到
#计算出如何定义R,F,M三个标准,即满足什么条件的R,C,F可以描述哪一类的客户
#先通过画图,查看数据的分布,
#R和F的数据量用每个数值在总书据所占的比例表示
R = data["Recency"].groupby(data["Recency"]).count()
R_percent = R/51394 #共有51394个数据
plt.rcParams["font.sans-serif"] = "Arial Unicode MS"
## 以R_percent的index为x轴的值,R_percent的values为y轴的值,
## 即x轴是R的值,y轴是这个R的值数量占所有R的值数量的百分比
plt.bar(R_percent.index, R_percent.values)
plt.title("R")
plt.show()
#
#同样的方法画出F的统计图
F = data["订单数量"].groupby(data["订单数量"]).count()
F_percent = F/51394
plt.rcParams["font.sans-serif"] = "Arial Unicode MS"
plt.bar(F_percent.index, F_percent.values)
plt.title("F")
plt.show()
#
##对于M,因为大多数用户的消费金额都差不多,用上面占比的方法画出来的图不明确
##因此,我们通过分箱的方式,从小到大,这里bins=100,分为100组,画出每组里汉欧消费金额的总个数量
##即,x轴是消费金额,y轴是频数
plt.hist(data["消费总金额"], bins =100)
plt.title("M")
plt.show()

本例中,我希望将这些数据平分,即平均得分为五等分,分别评级为1,2,3,4,5分。但这些数据明显呈现数据值越小,数量越大的情况。通常来说,将数据分成五级,我们用分箱的方法,分箱包括等宽分箱(cut),等深分箱(qcut)。等宽分箱显然不太适合这份数据,一个一个凑箱子的边界太繁琐。因此这里使用等深分箱的方法。

pandas中,等深分箱的结果并不一定是严格意义上的均分。因为有相同数值数据的存在,比如0,1,2,2,3,4,4,4,4,4,5,6,7,8,9这组数字,严格意义上的五等分应该是0,1,2|2,3,4|4,4,4|4,5,6|7,8,9。但这样把两个2分开放在两个箱子,4分开放在了三个箱子,显然是不合理的。因此pandas内部会通过一定的方法,优先将相同的数字分配到同一个箱子中,再考虑是否等分的问题。因此,用qcut算出来的结果并不是严格的等分,会出现一些箱子里的数据多一些,少一些的情况。

#判定R,F,M的评分标准
#最近一次消费距离现在时间越短,R越大 
data["R"] = pd.qcut(data["Recency"],q=5,labels=[5,4,3,2,1])
R_count = data["R"].value_counts()
data["F"] = pd.qcut(data["订单数量"],q=5,labels=[1,2,3,4,5])
F_count = data["F"].value_counts()
data["M"] = pd.qcut(data["消费总金额"],q=5,labels=[1,2,3,4,5])
M_count = data["M"].value_counts()
print(R_count)
print(F_count)
print(M_count)
print(data)

 可以看到,R,F,M基本上做到了五等分,并且成功得将它们评分为1~5分。

三、用户分类

通过最开始的RFM的定义可以得出,R,F,M三个维度虽然是五级的评分制,但RFM只是将用户分为8大类,也就是说每个维度可以用简单的二分法分为“好”与“不好”两种评价。“好”可以用1表示,“不好”可以用0表示,这样八类用户可以通过三位二进制来描述,RFM=000,001...111。比如000就是低价值用户。

因此,为了方便操作,我们需要将上面得到的R,F,M评分再简化,简化为0,1的二分类,并将R,F,M三个维度简化为一个维度,即上述的三位二进制码的形式。

def bi_classify(x):
    if x > 3:
        x = 1
    else:
        x = 0
    return x

data["R"] = data["R"].apply(bi_classify)
data["F"] = data["F"].apply(bi_classify)
data["M"] = data["M"].apply(bi_classify)
print(data[["R","F","M"]])

输出:
[51394 rows x 14 columns]
       R  F  M
0      1  1  1
1      1  1  1
2      1  1  1
3      0  1  1
4      1  1  1
...   .. .. ..
51389  0  0  0
51390  0  0  0
51391  0  0  0
51392  1  0  0
51393  0  0  0


#将R,F,M三个值维度合成一整个数据,像001,110,101,这样方便判断。
#通过astype函数,转换数据类型
data["RFM"] = data["R"].astype(str) + data["F"].astype(str) + data["M"].astype(str)
print(data["RFM"])

输出:
[51394 rows x 3 columns]
0        111
1        111
2        111
3        011
4        111
        ...
51389    000
51390    000
51391    000
51392    100
51393    000



def userClassify(x):
    if x=="111":
        return "高价值用户"
    elif x=="101":
        return "重点发展用户"
    elif x=="011":
        return "重点唤回用户"
    elif x=="001":
        return "重点潜力用户"
    elif x=="110":
        return "一般潜力用户"
    elif x=="100":
        return "一般发展用户"
    elif x=="010":
        return "一般维系用户"
    else:
        return "低价值用户"

data["用户类别"] = data["RFM"].apply(userClassify)
print(data["用户类别"])

输出:
0         高价值用户
1         高价值用户
2         高价值用户
3        重点唤回用户
4         高价值用户
          ...
51389     低价值用户
51390     低价值用户
51391     低价值用户
51392    一般发展用户
51393     低价值用户
Name: 用户类别, Length: 51394, dtype: object

  • 0
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三头猪等于一头大猪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值