Python|Python之RFM建模分析

1、RFM模型的含义
??RFM模型是衡量客户价值和客户创利能力的重要工具和手段。在众多的客户关系管理(CRM)的分析模式中,RFM模型是被广泛提到的。
??该模型通过一个客户的近期购买行为?、购买的总体频率(F)以及花了多少钱(M)三项指标来描述该客户的价值状况,从而能够更加准确地将成本和精力更精确的花在用户层次身上,实现针对性的营销。
??详细来说,R指的是客户最后一次下单时间距离今天多少天了,该指标与客户的复购和流失直接相关。F指标指的是客户的下单频率,即客户在某个时间段内共消费了多少次,该指标用于衡量客户消费的活跃度。M指标指的是客户在该时间段内共消费了多少钱,该指标用于反应客户对于公司的贡献值。
Python|Python之RFM建模分析
文章图片


2、RFM分析的前提条件

  • 最近有过交易行为的客户,再次发生交易行为的可能性高于最近没有交易行为的客户。
  • 交易频率高的客户,比交易频率低的客户,更有可能再次发生交易行为。
  • 过去所有交易总金额较大的客户,比过去所有交易总金额较小的客户,更有消费积极性。
3、原始数据
??本文数据集
RFM淘宝建模数据集免费版-机器学习文档类资源-CSDN下载
如果有需要的话,可以留言获取。如果觉得本文写的还不错,可以关注一下,获取更多精彩文章。
??原始数据集在这里先展示一下,让你对这个数据有一个主观印象。
Python|Python之RFM建模分析
文章图片

4、数据处理
1)什么是R、F、M呢?
  • “R”表示最近一次消费时间距离今天共有多少天。什么是最近一次消费时间呢?如果同一个人在不同时间有不同多个订单,那么该时间距离当前时间的差值的最小值,就是最近一次消费时间。
  • “F”表示某个人一段时间内的消费频次。
  • “M”表示一段时间内的消费总额。
  • Python|Python之RFM建模分析
    文章图片

2)所有代码来了
from operator import index from pickle import FALSE from numpy import loadtxt from numpy import sort from matplotlib import pyplot import numpy as np import pandas as pd import seaborn as sns import matplotlib.pyplot as plt#熟悉数据 df = pd.read_excel(r'C:\Users\Administrator\Desktop\RFM.xlsx') print(df.shape) print(df.sample(5))print('-------------------------保留有效数据---------------------------------------------------------') ''' 针对此数据集,我们先说一下什么是“有效数据”。“有效数据”指的就是有效购买,也就是说对应的“订单状态”字段显示的是“交易成功”,对于“退款”的记录,我们就直接将这个数据剔除掉。 ''' #保留有效数据 print("剔除之前共有:"+ str(df.shape[0]) + "条记录") df = df[df["订单状态"]=="交易成功"] print("剔除之后共有:"+ str(df.shape[0]) + "条记录")print('----------------------------选取有效字段 ------------------------------------------------------') ''' 通过上面的分析,我们知道了“R”、“F”、“M”三个指标的概念。鉴于此,我们只需要选取"买家昵称",“付款时间”,"实付金额"这三个字段,用于RFM模型的构建,其余字段用处不大,因此删除其余字段。 ''' #选取有效字段 df1 = df[["买家昵称","付款时间","实付金额"]] df1.index = np.arange(df1.shape[0]) print(df1.shape) print(df1.head())print('--------------------------缺失值处理--------------------------------------------------------') #缺失值处理 df1.isnull().sum(axis=0)print('--------------------------计算RFM三个指标--------------------------------------------------------') ''' 针对上述“R”、“F”、“M”三个指标的概念,我们对数据做一定的处理。由于 “R”表示的是最近一次消费时间距离今天共有多少天。但是数据集中只有每一天的“付款时间”字段。因此计算RFM指标之前,需要事先添加一个“天数”字段,求出每个“付款时间”距今共有多少天。“天数”越小,就表示最近一次的消费时间。 ??然后针对上述处理后的数据,做一个数据透视表。以“买家昵称”作为分组字段,对“天数”求最小值;对“付款昵称”计数;对“实付金额”求和,就可以得到我们想要的RFM三个指标。 '''#增加“天数”字段,用于计算“R”指标 df1["付款时间"] = pd.to_datetime(df1["付款时间"]) df1["天数"] = (pd.to_datetime("today")-df1["付款时间"]).dt.days print(df1.sample(10))df2 = pd.pivot_table(df1,index="买家昵称", values=["买家昵称","天数","实付金额"], aggfunc={"买家昵称":"count","天数":"min","实付金额":"sum"}) df2 = df2[["天数","买家昵称","实付金额"]] df2.columns = ["R","F","M"] df2.reset_index() print(df2.shape) print(df2.head(10))print('-------------------------建立打分机制--------------------------------------------------------') ''' 通过上述分析,我们已经得到了每一个用户的“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 1def 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 5def 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 5df2["R-SCORE"] = df2["R"].apply(func1) df2["F-SCORE"] = df2["F"].apply(func2) df2["M-SCORE"] = df2["M"].apply(func3) print(df2) df2.sample(10)print('-------------------------用户贴标签--------------------------------------------------------') ''' 前面的步骤中,我们已经根据业务需求,对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: return 1 else: return 0def func2(x): if x>avg_f: return 1 else: return 0def func3(x): if x>avg_m: return 1 else: return 0df2["R-SCORE是否大于均值"] = df2["R-SCORE"].apply(func1) df2["F-SCORE是否大于均值"] = df2["F-SCORE"].apply(func1) df2["M-SCORE是否大于均值"] = df2["M-SCORE"].apply(func1) print(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) print(df2)print('-------------------------可视化展示--------------------------------------------------------') print('-------------------------绘制不同类型客户的人数对比-----------------------------------------------------') df3 = df2.groupby("标签", as_index=FALSE).agg({"标签":"count"}).rename(columns={'标签': '汇总数'}) df3["不同客户的占比"] = df3["汇总数"].apply(lambda x:x/np.sum(df3["汇总数"])) print(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) plt.rcParams['font.sans-serif']=['SimHei']print('-------------------------绘制不同类型客户人数占比图--------------------------------------------------------')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'] labels = ['一般客户','重要唤回客户','重要挽回客户', '流失客户']#根据实际情况来 colors = ['#9999ff','#ff9999','#7777aa','#2442aa'] explode = [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)print('-------------------------绘制不同类型客户累计消费金额-------------------------------------------------------')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)print('-------------------------绘制不同类型客户金额占比图-------------------------------------------------------')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]labels = ['一般客户','重要唤回客户','重要挽回客户', '流失客户']#根据实际情况来 colors = ['#9999ff','#ff9999','#7777aa','#2442aa'] explode = [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)plt.show()

Python|Python之RFM建模分析
文章图片

【Python|Python之RFM建模分析】

    推荐阅读