社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

用 Python 轻松实现数据分析中的 RFM 建模

Python程序员 • 3 年前 • 228 次点击  




今天给大家分享的是如何用python实现RFM建模。

RFM模型的含义

RFM模型是衡量客户价值和客户创利能力的重要工具和手段。在众多的客户关系管理(CRM)的分析模式中,RFM模型是被广泛提到的。


该模型通过一个客户的近期购买行为(R)、购买的总体频率(F)以及花了多少钱(M)三项指标来描述该客户的价值状况,从而能够更加准确地将成本和精力更精确的花在用户层次身上,实现针对性的营销。


详细来说,R指的是客户最后一次下单时间距离今天多少天了,该指标与客户的复购和流失直接相关。F指标指的是客户的下单频率,即客户在某个时间段内共消费了多少次,该指标用于衡量客户消费的活跃度。M指标指的是客户在该时间段内共消费了多少钱,该指标用于反应客户对于公司的贡献值。



RFM分析的前提条件:
  • 最近有过交易行为的客户,再次发生交易行为的可能性高于最近没有交易行为的客户。

  • 交易频率高的客户,比交易频率低的客户,更有可能再次发生交易行为。

  • 过去所有交易总金额较大的客户,比过去所有交易总金额较小的客户,更有消费积极性。

原始数据

原始数据集在这里先展示一下,让你对这个数据有一个主观印象。

(点击放大)

数据处理

1)什么是R、F、M呢?

“R”表示最近一次消费时间距离今天共有多少天。什么是最近一次消费时间呢?如果同一个人在不同时间有不同多个订单,那么该时间距离当前时间的差值的最小值,就是最近一次消费时间。
“F”表示某个人一段时间内的消费频次。
“M”表示一段时间内的消费总额。

2)熟悉数据集

熟悉数据集,就是在进行数据处理之前,应该先熟悉数据,只有对数据充分熟悉之后,才能更好的进行分析。

熟悉数据常用的方法和属性有shape、head()、tail()、sample()、info()、describe()。
df = pd.read_excel(r"C:\Users\黄伟\Desktop\RFM_Model\RFM.xlsx")
display(df.shape)
display(df.sample(5))
结果如下:

从上述结果中可以发现:这笔数据总共有28833行条记录,12列。观察上图,可以清楚地看到每一列数据代表什么含义。

3)保留有效数据

针对此数据集,我们先说一下什么是“有效数据”。“有效数据”指的就是有效购买,也就是说对应的“订单状态”字段显示的是“交易成功”,对于“退款”的记录,我们就直接将这个数据剔除掉。
display("剔除之前共有:"+ str(df.shape[0]) + "条记录")
df = df[df["订单状态"]=="交易成功"]
display("剔除之后共有:"+ str(df.shape[0]) + "条记录")
结果如下:

4)选取有效字段

通过上面的分析,我们知道了“R”、“F”、“M”三个指标的概念。鉴于此,我们只需要选取"买家昵称",“付款时间”,"实付金额"这三个字段,用于RFM模型的构建,其余字段用处不大,因此删除其余字段。
df1 = df[["买家昵称","付款时间","实付金额"]]
df1.index = np.arange(df1.shape[0])
display(df1.shape)
display(df1.head())
结果如下:

5)缺失值处理
df1.isnull().sum(axis=0)
结果如下:

从上述结果中可以发现:各字段中没有缺失值,因此不需要做任何处理。

RFM建模过程

1)计算RFM三个指标

① 增加“天数”字段,用于计算“R”指标

针对上述“R”、“F”、“M”三个指标的概念,我们对数据做一定的处理。由于 “R”表示的是最近一次消费时间距离今天共有多少天。但是数据集中只有每一天的“付款时间”字段。因此计算RFM指标之前,需要事先添加一个“天数”字段,求出每个“付款时间”距今共有多少天。“天数”越小,就表示最近一次的消费时间。

然后针对上述处理后的数据,做一个数据透视表。以“买家昵称”作为分组字段,对“天数”求最小值;对“付款昵称”计数;对“实付金额”求和,就可以得到我们想要的RFM三个指标。
df1["付款时间"] = pd.to_datetime(df1["付款时间"])
df1["天数"] = (pd.to_datetime("today")-df1["付款时间"]).dt.days
display(df1.sample(10))
结果如下:

② 计算RFM三个指标
df2 = pd.pivot_table(df1,index="买家昵称",
values=["买家昵称","天数","实付金额"],
aggfunc={"买家昵称":"count","天数":"min","实付金额":"sum"})
df2 = df2[["天数","买家昵称","实付金额"]]
df2.columns = ["R","F","M"]
df2.reset_index()
display(df2.shape)
display(df2.head(10))
结果如下:

2)用户分层打分

通过上述分析,我们已经得到了每一个用户的“R”、“F”、“M”值。接下来要做的,就是给每一个用户进行分层。这里我们需要建立一个评判标准,由于RFM模型本身就是需要根据不同场景和业务需求来建立的,因此这个分层标准,也是需要我们沟通业务后,得到最后的分层标准。

以R指标为例进行说明,根据上表我们知道,R表示每个用户最后一次购买时间距离今天共经历了多少天。当这个值越小,说明用户近期又回购了此产品;当这个值越大,说明用户已经好久没有再次购买产品了,这个用户很有可能流失掉了(猜测)。

基于上述分析,我们采用通用的5分制打分法,对RFM进行分类打分。

说明:由于这个数据集时间较早,因此计算出来的最近一次购买时间距离今天的天数,会特别大,但是没有关系,我们演示这个案例只是为了说明RFM模型的建模过程,实际中,肯定是过几个月进行一次RFM建模是比较好的,这里你只需要知道原理就好。

对于R指标来说:我们可以求出,R指标最小值是660天,我们以30天作为时间间隔,660-690天,打5分;690-720,打4分;720-750打3分;750-780打2分;>780,打1分。

对于F指标来说:我们可以求出,F指标最小值是1次,我们以1次作为时间间隔,0-2,打1分;2-3,打2分;3-4,打3分;4-5,打4分;>5,打5分。

对于M指标来说:我们可以求出,M指标最小值是0.005元,我们以500元作为时间间隔,0-50,打1分;50-100,打2分;100-150,打3分;150-200,打4分;>200,打5分。

至此,我们已经建立好了打分标准,下面我们开始对每个用户进行分类打分。
def func1(x):
if x>=660 and x<690:
return 5
elif x>=690 and x<720:
return 4
elif x>=720 and x<750:
return 3
elif x>=750 and x<780:
return 2
elif x>=780:
return 1

def func2(x):
if x>=0 and x<2:
return 1
elif x>=2 and x<3:
return 2
elif x>=3 and x<4:
return 3
elif x>=4 and x<5:
return 4
elif x>=5:
return 5

def func3(x):
if x>=0 and x<50:
return 1
elif x>=50 and x<100:
return 2
elif x>=100 and x<150:
return 3
elif x>=150 and x<200:
return 4
elif x>=200:
return 5

df2["R-SCORE"] = df2["R"].apply(func1)
df2["F-SCORE"] = df2["F"].apply(func2)
df2["M-SCORE" ] = df2["M"].apply(func3)
df2.sample(10)
结果如下:

3)用户贴标签

前面的步骤中,我们已经根据业务需求,对RFM指标进行了分类打分,得到了R-SCORE、F-SCORE、M-SCORE三个指标。接下来,我们需要给每个用户贴标签,这里有两种方式可以进行用户贴标签。

第一种:根据业务场景和业务来分配全重,对于RFM这3个指标,你更看重哪个指标,就赋予它相应较大一点的权重,比如说赋予的权重是3:1:2。

第二种:完全根据单独的RFM标签来计算,比如说:R-SCORE>avg(R-SCORE)、F-SCORE>avg(F-SCORE)、M-SCORE>avg(M-SCORE),表示一个客户近期有购买,购买频率高于所有客户平均购买频率,购买金额高于所有客户的平均购买金额,因此我们贴上一个“重要挽留客户”的标签。

下面以第二种方法进行说明。根据上述叙述,每个指标有两种情况,要么>avg(),要么avg(),我们记为1;当指标


① 第一步
avg_r = df2["R-SCORE"].mean()
avg_f = df2["F-SCORE"].mean()
avg_m = df2["M-SCORE"].mean()
display(avg_r,avg_f,avg_m)
结果如下:

② 第二步
def func1(x):
if x>avg_r:
return 1
else:
return 0

def func2(x):
if x>avg_f:
return 1
else:
return 0

def func3(x):
if x>avg_m:
return 1
else:
return 0

df2["R-SCORE是否大于均值"] = df2["R-SCORE"].apply(func1)
df2["F-SCORE是否大于均值"] = df2["F-SCORE"].apply(func1)
df2["M-SCORE是否大于均值"] = df2["M-SCORE"].apply(func1)
display(df2.sample(10))
结果如下:

③ 第三步
def functions(x):
if x.iloc[0]==1 and x.iloc[1]==1 and x.iloc[2]==1:
return "重要价值客户"
elif x.iloc[0]==1 and x.iloc[1]==1 and x.iloc[2]==0:
return "潜力客户"
elif x.iloc[0]==1 and x.iloc[1]==0 and x.iloc[2]==1:
return "重要深耕客户"
elif x.iloc[0]==1 and x.iloc[1]==0 and x.iloc[2]==0:
return "新客户"
elif x.iloc[0]==0 and x.iloc[1]==1 and x.iloc[2]==1:
return "重要唤回客户"
elif x.iloc[0]==0 and x.iloc[1]==1 and x.iloc[2]==0:
return "一般客户"
elif x.iloc[0]==0 and x.iloc[1]==0 and x.iloc[2]==1:
return "重要挽回客户"
elif x.iloc[0]==0 and x.iloc[1]==0 and x.iloc[2]==0:
return "流失客户"
df2["标签"] = df2[["R-SCORE是否大于均值","F-SCORE是否大于均值","M-SCORE是否大于均值"]].apply(functions,axis=1)
df2.sample(10)
结果如下:

4)可视化展示

① 绘制不同类型客户的人数对比
df3 = df2.groupby("标签").agg({"标签":"count"})
df3["不同客户的占比"] = df3["标签"].apply(lambda x:x/np.sum(df3["标签"]))
df3 = df3.sort_values(by="标签",ascending=True)

plt.figure(figsize=(6,4),dpi=100)
x = df3.index
y = df3["标签"]

plt.barh(x,height=0.5,width=y,align="center")
plt.title("不同类型客户的人数对比")

for x,y in enumerate(y):
plt.text(y+450,x,y,ha="center",va="center",fontsize=14)

plt.xticks(np.arange(0,10001,2000))

plt.tight_layout()
plt.savefig("不同类型客户的人数对比",dpi=300)
结果如下:

② 绘制不同类型客户人数占比图
df3 = df2.groupby("标签").agg({"标签":"count"})
df3["不同客户的占比"] = df3["标签"].apply(lambda x:x/np.sum(df3["标签"]))
df3 = df3.sort_values(by="标签",ascending=True)

plt.figure(figsize=(7,4),dpi=100)
x = df3["不同客户的占比"]

labels = ['潜力客户', '一般客户', '重要价值客户', '重要唤回客户', '重要深耕客户', '新客户', '重要挽回客户', '流失客户']
colors = ['#9999ff','#ff9999','#7777aa','#2442aa','#dd5555','deeppink','yellowgreen','lightskyblue']

explode = [0,0,0,0,0,0,0,0]

patches,l_text = plt.pie(x,labels=labels,colors=colors,
explode=explode,startangle=90,counterclock=False)
for t in l_text:
t.set_size(0)
plt.axis("equal")
plt.legend(loc=(0.001,0.001),frameon=False)

plt.title("不同类型客户人数占比图")

plt.savefig("不同类型客户人数占比图",dpi=300)
结果如下:

③ 绘制不同类型客户累计消费金额
df3 = df2.groupby("标签").agg({"M":"sum"})
df3["M"] = df3["M"].apply(lambda x:round(x))
df3["不同客户的占比"] = df3["M"].apply(lambda x:x/np.sum(df3["M"]))
df3 = df3.sort_values(by="M",ascending=True)

plt.figure(figsize=(6,4),dpi=100)
x = df3.index
y = df3["M"]

plt.barh(x,height=0.5,width=y,align="center")
plt.title("不同类型客户累计消费金额")

for x,y in enumerate(y):
plt.text(y+45000,x,y,ha="center",va="center",fontsize=14)

plt.xticks(np.arange(0,700001,100000))
plt.tight_layout()
plt.savefig("不同类型客户累计消费金额",dpi=300)
结果如下:

④ 绘制不同类型客户金额占比图
df3 = df2.groupby("标签").agg({"M":"sum"})
df3["M"] = df3["M"].apply(lambda x:round(x))
df3["不同客户的占比"] = df3["M"].apply(lambda x:x/np.sum(df3["M"]))
df3 = df3.sort_values(by="M",ascending=True)

plt.figure(figsize=(7,4),dpi=100)
x = df3["不同客户的占比"]

labels = ['潜力客户', '一般客户', '重要价值客户', '重要唤回客户', '重要深耕客户', '新客户', '重要挽回客户', '流失客户']
colors = ['#9999ff','#ff9999','#7777aa','#2442aa','#dd5555','deeppink','yellowgreen','lightskyblue']

explode = [0,0,0,0,0,0,0,0]

patches,l_text= plt.pie(x,labels=labels,colors=colors,
explode=explode,startangle=90,counterclock=False)
for t in l_text:
t.set_size(0)

plt.axis("equal")
plt.legend(loc=(0.001,0.001),frameon=False)

plt.title("不同类型客户金额占比图")

plt.savefig("不同类型客户金额占比图",dpi=300)
结果如下:

结论

① 通过上面的可视化展示可以发现,重要挽回客户7102人,虽然只占总人数的28%,但是他们的累计消费金额却是最高的,达到了639763元。重要挽回客户指的是“做出最大购买,但很久没有回来购买”,这一部分人已经濒临流失边缘,极大可能会流失,但是这一部分人对于公司的实际贡献来说,具有很大价值。因此可以采取重点联系或拜访的形式,调查回购率低的原因,从而提高留存率。

② 通过上面的可视化展示可以发现,新客户5002人,也占总人数的20%,他们的累计消费金额也达到了134085元。这一部分人最近有交易,交易频率不高,金额小,很容易丢失,但是有推广价值。针对这一部分群体,我们可以采取社区活动这种形式,提供免费试用产品,提高客户兴趣,对于创建品牌知名度很有必要。

③ 通过上面的可视化展示可以发现,流失客户8601人,具有最大占比34%,他们的累计消费金额也达到了200854元。流失客户表示最后一次购买的时间很长,金额小,订单数少,属于冬眠客户。针对上面的新客户和这里的流失客户的处理有两种办法,如果说这部分人的消费金额较大,对公司的价值较大,就需要想办法恢复这部分客户的兴趣;如果说这部分人的消费金额较小,暂时放弃无价值用户,主要将运营的中心放在如何留住核心收入来源的客户群体之上,以及通过各种方式召回“重要挽回客户”。




Python 程序员深度学习的“四大名著”:



这四本书着实很不错!我们都知道现在机器学习、深度学习的资料太多了,面对海量资源,往往陷入到“无从下手”的困惑出境。而且并非所有的书籍都是优质资源,浪费大量的时间是得不偿失的。给大家推荐这几本好书并做简单介绍。


获得方式:


1.扫码关注 “高富帅程序员” 公众号
2.后台回复关键词:4books
注:此处建议复制,不然容易打错

▲长按扫描关注,回复4books即可获取
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/108621
 
228 次点击