对某在线教育平台用户使用RFM模型按价值分类
对某在线教育平台用户使用RFM模型按价值分类
- 说在前面
- 项目背景
- RFM分析
- RFM分析过程
- 明确目的
- 分析原因
- 对R,F,M值进行定义
- 统计R,F,M值
- 给R,F,M值“打分”
- 计算价值平均值
- 用户分类
- 数据可视化
- 数据预处理
- 引入数据分析python库
- 设置绘图中文支持
- 排除警告
- 读入excel处理好的数据
- R值,F值,M值
- 构建RFM模型,对用户进行分类
- 建立RFM模型
- 对用户分类
- 柱形图
- 饼图
- 树地图
- 得出结论
- 提出建议
- end
点击跳转到总目录
点击跳转基于RFM模型的Kmeans聚类算法实现
说在前面
项目背景
- 某在线教育平台,在对2019年用户进行盘点时发现,用户运营过于粗放,没能做到用户分类运营。老板想在新的一年里对不同的用户进行有针对性的营销,达到降低成本提高收入,提升投资回报率的目的。
- 使用工具:excel+jupyter
- excel:数据处理
- jupyter:数据可视化
RFM分析
- RFM分析是根据客户活跃程度和交易金额贡献,进行客户价值细分的一种方法;
- 可以通过R,F,M三个维度,将客户划分为8种类型。
RFM分析过程
- 计算RFM各项分值
R_S,距离当前日期越近,得分越高,最高5分,最低1分
F_S,交易频率越高,得分越高,最高5分,最低1分
M_S,交易金额越高,得分越高,最高5分,最低1分 - 归总RFM分值
RFM=100R_S+10F_S+1*M_S - 根据RFM分值对客户分类
明确目的
该在线教育平台的课程服务形式有两种:
- 图文音频视频形式的课程,用户自学这类课程的价格是100~1000元
- 提供学习服务,如作业答疑,1对1辅导等的培训类课程,这类课程的售价是1000~10000元。
- 目前的问题是:如何对用户分类,从而实现用户分类运营。可以使用RFM模型分析方法对用户按价值分类,从而实现精细化运营。
分析原因
对R,F,M值进行定义
- R值:某用户最后一次消费距离2020年1月1日的天数
- F值:某用户在2019年这一年的消费次数
- M值:某用户在2019年这一年的消费金额
- 要得到R,F,M这三个指标,需要数据的字段包括:用户ID(用户在该教育平台中唯一的编号),订单号(唯一标识用户购买课程的订单编号),订单金额(购买课程花了多少钱,单位是元),下单时间(购买课程的时间)。如下截图所示,数据来源网络,共有9935行x4列数据
统计R,F,M值
- 为了统计R,F,M值,需要将数据按照用户ID进行分组汇总,即每一行是一个用户的消费行为,如下表所示
给R,F,M值“打分”
- R值打分:当前业务处于快速发展期,用户一般是通过课程优惠类的拉新活动吸引来的,根据统计用户注册后一般会在3天内发生购买课程,每周都会有上新,7天是一个重要的时间节点,对于图文音频视频课程,则一般会在上线后40天更新完毕,培训类课程的授课周期一般是90天
- F值打分:根据当前业务发展需要,购买次数超过三次产生的利润才能覆盖获客成本,全平台的用户平均完成订单数是8单,中位数是12单,根据二八法则,期望20%的用户能贡献80%的利润,80%分位数上的用户订单数是16单
- M值打分:按照每20%分位数为一个档次,分别计算出该批用户20%,40%,60%,80%分位数的总消费金额
- 最终确定的打分规则见下表
- 根据这个打分规则,可以在前面的表格里加上二值打分,F值打分,M值打分,这三列并填上对应的分值,如下表所示
计算价值平均值
- 分别计算出R值打分,F值打分,M值打分这三列的平均值。R值打分平均值约为2.6,F值打分平均值3.54,M值打分平均值2.36
用户分类
- 对用户的情况进行分类,记录R,F,M三个值是高于平均值还是低于平均值。
- 如下表所示,如如果该用户的R值打分大于平均值,就在“R值高低”列记录为“高”,否则记录为“低”,F值,M值也同理。
数据可视化
数据预处理
引入数据分析python库
# ! pip install squarify
# 由于系统 python jupyter路径不一致所有各自安装的包不能通用
# ! pip install squarify
# jupyter 命令行下 运行这个即可import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
import squarifyfrom mpl_toolkits.mplot3d import Axes3D
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = Falseprint(np.__version__)
print(pd.__version__)
print(mpl.__version__)
设置绘图中文支持
%matplotlib inline
mpl.rcParams["font.family"] = "SimHei"#解决中文乱码问题
mpl.rcParams["axes.unicode_minus"]=False # 用来正常显示负号
plt.rcParams['font.sans-serif']=['SimHei'] # 用来正常显示中文标签%config InlineBackend.figure_format = 'svg'
排除警告
import warnings
warnings.filterwarnings("ignore")
读入excel处理好的数据
jiaoyu2 = pd.read_excel("22在线教育2.xlsx",sheet_name = "Sheet6",encoding="utf-8")
jiaoyu2.head(10)
# 备份数据
data_edu3 = jiaoyu2.copy()
# 认识以下整体数据
data_edu3.info()# R值:用户最后一次消费距离2020/1/1的天数
# F值:用户在2019年消费次数
# M值:用户在2019年消费金额data_edu3.describe()
R值,F值,M值
- 主要是对比和excel处理数据的区别
#R值
a = []
for i in data_edu3["最近一次消费时间间隔(R)"]:if 0<=i<3:a.append(5)elif 3<=i<7:a.append(4)elif 7<=i<40:a.append(3)elif 40<=i<90:a.append(2)else:a.append(1)
# print(a,len(a),type(a))
data_edu3.insert(4,"R值打分",a)
# data_edu3.head(20)
#F值
b = []
for i in data_edu3["消费频率(F)"]:if 0<=i<3:b.append(1)elif 3<=i<8:b.append(2)elif 8<=i<12:b.append(3)elif 12<=i<16:b.append(4)else:b.append(5)
data_edu3.insert(5,"F值打分",b)
# data_edu3.head(20)
#M值
c = []
for i in data_edu3["消费金额(M)"]:if 0<=i<500:c.append(1)elif 500<=i<9500:c.append(2)elif 9500<=i<15000:c.append(3)elif 15000<=i<25000:c.append(4)else:c.append(5)
data_edu3.insert(6,"M值打分",c)
data_edu3.head(20)
构建RFM模型,对用户进行分类
建立RFM模型
# 由上面可知
b = data_edu3["R值打分"].mean()# R值打分均值 y轴
c = data_edu3["F值打分"].mean()# F值打分均值 x轴
a = data_edu3["M值打分"].mean()# M值打分均值 z轴print("R值:",b,"F值:",c,"M值:",a)
# delta图像调节参数
import turtle as tdef plot_dsw(data, delta, color, categories_nr):x, y, z, dx, dy, dz = (0, 0, 0,categories_nr+delta, categories_nr+delta, data.iloc[:, 6].max())#薪资b = categories_nr/2 + 0.5fig = plt.figure(figsize=(6.8, 5.3), dpi=180)ax = Axes3D(fig)# 绘制(x, 3.54, 3.43)线xc = np.arange(-1, dx+1, 0.01)yc = 3.54 * np.ones(len(xc))zc = 3.43 * np.ones(len(xc))ax.plot(xc, yc, zc, color='#191970')# 绘制(2.6, y, 3.43)线yc1 = np.arange(-1, dy+1, 0.01)xc1 = 2.6 * np.ones(len(yc1))zc1 = 3.43 * np.ones(len(yc1))ax.plot(xc1, yc1, zc1, color='#191970')# 绘制(2.6, 3.54 ,z)线zc2 = np.arange(-1, dz+1, 0.01)yc2 = 3.54 * np.ones(len(zc2))xc2 = 2.6 * np.ones(len(zc2))ax.plot(xc2, yc2, zc2, color='#191970')xx = [x, x, x+dx, x+dx, x]yy = [y, y+dy, y+dy, y, y]kwargs = {'color': color}ax.plot3D(xx, yy, [z]*5, **kwargs)# 绘制底面ax.plot3D(xx, yy, [z+dz]*5, **kwargs)# 绘制顶面ax.plot3D([x, x], [y, y], [z, z+dz], **kwargs)# 绘制边线ax.plot3D([x, x], [y+dy, y+dy], [z, z+dz], **kwargs)# 绘制边线ax.plot3D([x+dx, x+dx], [y+dy, y+dy], [z, z+dz], **kwargs)# 绘制边线ax.plot3D([x+dx, x+dx], [y, y], [z, z+dz], **kwargs)# 绘制边线# 绘制平面# x 平面Y_p1 = np.arange(0, 5, 0.01)X_p1 = 2.6 * np.ones(len(Y_p1))X, Y = np.meshgrid(X_p1, Y_p1)Z_p1 = np.linspace(0, data.iloc[:, 6].max(), 500)Z = np.meshgrid(Z_p1, Z_p1)[0]ax.plot_surface(X, Y, Z, alpha=0.45, color='gray')# y平面X_p2 = np.arange(0, 5, 0.01)Y_p2 = 3.54 * np.ones(len(X_p2))X1, Y1 = np.meshgrid(Y_p2, X_p2)Z_p2 = np.linspace(0, data.iloc[:, 6].max(), 500)Z1 = np.meshgrid(Z_p2, Z_p2)[0]ax.plot_surface(Y1, X1, Z1, alpha=0.35, color='gray')# z平面X_p2 = np.arange(0, 5, 0.01)Z_p2 = 3.43 * np.ones(len(X_p2))X1, Y1 = np.meshgrid(X_p2, X_p2)
# Z_p2 = np.linspace(0, data.iloc[:, 6].max(), 500)#斜平面Z1 = np.meshgrid(Z_p2, Z_p2)[0]ax.plot_surface(Y1, X1, Z1, alpha=0.36, color='gray')ax.set_xlim(0, dx)ax.set_ylim(0, dy)ax.set_zlim(0, dz)# ax.view_init(elev=20,azim=0)#添加注释ax.text(3.8, 4.8, 4.5, 'R高F高M高-高价值客户1', (1,2,3), color='r', alpha=1)ax.text(3.5, 4.9, 1.5, 'R高F高M低-一般价值客户5', (1,2,3), color='r', alpha=1)ax.text(4, 0, 3.5, 'R高F低M低-一般发展客户8', (1,2,3), color='r', alpha=1)ax.text(3.5,1.5, 5, 'R高F低M高-重点发展客户4', (1,2,3), color='r', alpha=1)ax.text(0.8, 4, 5, 'R低F高M高-重点保持客户2', (1,2,3), color='r', alpha=1)ax.text(0, 4.9, 1.5, 'R低F高M低-一般保持客户6', (1,2,3), color='r', alpha=1)ax.text(0.5, 1.6, 4.5, 'R低F低M高-重点挽留客户3', (1,2,3), color='r', alpha=1)ax.text(0.1, 1.6, 2, 'R低F低M低-潜在客户7', (1,2,3), color='r', alpha=1)ax.scatter(data['R值打分'], data['F值打分'], data['M值打分'], color='#FF00FF')ax.set_xlabel('最近一次消费时间间隔(R)', color='b', fontsize=13) ax.set_ylabel('消费频率(F)', color='b', fontsize=13) ax.set_zlabel('消费金额(M)', color='b', fontsize=13)ax.set_title('RFM模型分析', fontsize=16)
plot_dsw(data_edu3, 1, '#0000FF', 4)
对用户分类
def filter_categories(data_info, center, zone):if zone == 1:data_zone1 = data_info.loc[(data_info.iloc[:, 4] > center[0]) & (data_info.iloc[:, 5]> center[1]) \& (data_info.iloc[:, 6] > center[2]), '客户 Id']return data_zone1elif zone == 2:data_zone2 = data_info.loc[(data_info.iloc[:, 4] <= center[0]) & (data_info.iloc[:, 5] > center[1]) \& (data_info.iloc[:, 6] > center[2]), '客户 Id']return data_zone2elif zone == 3:data_zone3 = data_info.loc[(data_info.iloc[:, 4] <= center[0]) & (data_info.iloc[:, 5] > center[1]) \& (data_info.iloc[:, 6] <= center[2]), '客户 Id'] return data_zone3elif zone == 4:data_zone4 = data_info.loc[(data_info.iloc[:, 4] > center[0]) & (data_info.iloc[:, 5] > center[1]) \& (data_info.iloc[:, 6] <= center[2]), '客户 Id']return data_zone4elif zone == 5:data_zone5 = data_info.loc[(data_info.iloc[:, 4] > center[0]) & (data_info.iloc[:, 5] <= center[1]) \& (data_info.iloc[:, 6] > center[2]), '客户 Id'] return data_zone5elif zone == 6:data_zone6 = data_info.loc[(data_info.iloc[:, 4] <= center[0]) & (data_info.iloc[:, 5] <= center[1]) \& (data_info.iloc[:, 6] > center[2]), '客户 Id'] return data_zone6elif zone == 7:data_zone7 = data_info.loc[(data_info.iloc[:, 4] <= center[0]) & (data_info.iloc[:, 5] <= center[1]) \& (data_info.iloc[:, 6] <= center[2]), '客户 Id'] return data_zone7elif zone == 8:data_zone8 = data_info.loc[(data_info.iloc[:, 4] > center[0]) & (data_info.iloc[:, 5] <= center[1]) \& (data_info.iloc[:, 6] <= center[2]), '客户 Id'] return data_zone8
x = []
for y in range(1,9):z = (filter_categories(data_edu3, (2.6,3.54,3.43), y).shape[0])x.append(z)
print(x,len(x),type(x))
柱形图
plt.figure(figsize = (500,200))#设置画布大小
xx = np.array(["R高F高M高-高价值客户1","R低F高M高-重点保持客户2","R低F低M高-重点挽留客户3","R高F低M高-重点发展客户4","R高F高M低-一般价值客户5","R低F高M低-一般保持客户6","R低F低M低-潜在客户7","R高F低M低-一般发展客户8"])
yy = np.array(x)a = xx
b = yy
plt.bar(a,b,width=0.5,align="center",label="用户数")
plt.title("不同价值类别的用户数量",loc="center")
for ab,cd in zip(a,b):plt.text(ab,cd,cd,ha="center",va = "bottom",fontsize=12)
plt.xlabel('用户价值分别')
plt.xticks(rotation=90)
plt.ylabel('用户数')
plt.legend()#显示图例
#将图表保存到本地
# plt.savefig("E:/编程语言-青铜/面试准备/01.简历/03.简历几个模块/0猎聘/6.jpg")
饼图
# 饼图
plt.subplot(1,1,1)
# yy 上面有
xxx = ["R高F高M高-高价值客户1","R低F高M高-重点保持客户2","R低F低M高-重点挽留客户3","R高F低M高-重点发展客户4","R高F高M低-一般价值客户5","R低F高M低-一般保持客户6","R低F低M低-潜在客户7","R高F低M低-一般发展客户8"]
explode = [0.1,0,0,0,0,0,0,0]#让第一块离圆心远一点
labeldistance = 1.1
plt.pie(yy,labels = xxx,autopct = '%.0f%%',shadow = True,explode = explode,radius = 1.0,labeldistance = labeldistance)
#设置标题
plt.title("不同价值类别的用户数量",loc="center")# plt.savefig("E:/编程语言-青铜/面试准备/01.简历/03.简历几个模块/0猎聘/7.jpg")
树地图
# 绘制树地图import squarify
# 指定每一块的大小
size = np.array([204, 118, 27, 56, 35, 38, 161, 151])
# 指定每一块的文字标签
fenlei = xx
# 指定每一块的数值标签
rate = np.array(["26%","15%","3%","7%","4%","5%","20%","19"])
# 指定每一块的颜色
colors = ['steelblue','#9999ff','red','indianred','green','yellow','orange']
# 绘图
plot = squarify.plot(sizes = size,label = fenlei,color = colors,value = rate,edgecolor = 'white',linewidth = 3)
# 设置标题大小
plt.title('不同价值类别的用户数量',fontdict = {'fontsize':12})
# 去除坐标轴
plt.axis('off')
# 去除上边框和右边框的刻度
plt.tick_params(top = 'off',right = 'off')
# 保存图表到本地
# plt.savefig("E:/编程语言-青铜/面试准备/01.简历/03.简历几个模块/0猎聘/7.jpg")
得出结论
- 从上面数据可视化的图中可以发现
- 重要价值用户最多,说明有很多种子用户
- 一般挽留和一般发展用户也较多用户呈现出较高价值和较低价值都很多的情况
提出建议
- 通过分类后,每个用户都有其对应的价值标签,例如用户10015是一般价值用户,用户10030是重要价值用户。这就使运营人员了解到平台上哪些用户是最好的用户,哪些用户是无价值用户,哪些用户有可能流失。
- 这就可以针对不同的用户,制定不同的运营策略,具体的策略描述如下表所示
end
- 以上便是我对这份在线教育用户数据进行的一次探索分析,相信其中会有很多不足之处,欢迎有缘读到此篇文章的小朋友们批评指正,如有能启发或帮助到你的地方,我将倍感荣幸。(●’◡’●)
对某在线教育平台用户使用RFM模型按价值分类相关推荐
- 在线教育平台的数据分析——用户精细化运营
文章列表 篇1:<在线教育平台的数据分析--用户精细化运营> 篇2:<在线教育平台的数据分析--课程分级> 篇3:<在线教育平台的数据分析--业务流程指标的计算> ...
- 在线教育平台的数据分析——用户的地域分布
文章列表 篇1:<在线教育平台的数据分析--用户精细化运营> 篇2:<在线教育平台的数据分析--课程分级> 篇3:<在线教育平台的数据分析--业务流程指标的计算> ...
- Java怎么做三端_Java三端分离开发在线教育平台
第1章 课程项目整体概述(整体介绍及Eclipse,Maven,新浪SAE软件平台介绍) 系统通过maven构建一个portal站,在sae上部署,让同学们感受一下互联网应用的魅力: 1-1 --课程 ...
- 第三百九十二节,Django+Xadmin打造上线标准的在线教育平台—sql注入攻击,xss攻击,csrf攻击...
第三百九十二节,Django+Xadmin打造上线标准的在线教育平台-sql注入攻击,xss攻击,csrf攻击 sql注入攻击 也就是黑客通过表单提交的地方,在表单里输入了sql语句,就是通过SQL语 ...
- Django+xadmin打造在线教育平台(十)
目录 在线教育平台(一) 在线教育平台(二) 在线教育平台(三) 在线教育平台(四) 在线教育平台(五) 在线教育平台(六) 在线教育平台(七) 在线教育平台( ...
- 第三百八十九节,Django+Xadmin打造上线标准的在线教育平台—列表筛选结合分页...
第三百八十九节,Django+Xadmin打造上线标准的在线教育平台-列表筛选结合分页 根据用户的筛选条件来结合分页 实现原理就是,当用户点击一个筛选条件时,通过get请求方式传参将筛选的id或者值, ...
- 第三百八十一节,Django+Xadmin打造上线标准的在线教育平台—xadmin全局配置
第三百八十一节,Django+Xadmin打造上线标准的在线教育平台-xadmin全局配置 1.xadmin主题设置 要使用xadmin主题,需要在一个app下的adminx.py后台注册文件里,写一 ...
- 基于SpringBoot+Vue前后端分离的在线教育平台项目
基于SpringBoot+Vue前后端分离的在线教育平台项目 赠给有缘人,希望能帮助到你!也请不要吝惜你的大拇指,你的Star.点赞将是对我最大的鼓励与支持! 开源传送门: 后台:Gitee | Gi ...
- 数仓项目——在线教育平台离线数据仓库效果展示
背景:基于阿里云的3台ECS云服务器搭建了在线教育平台的离线数据仓库,本文仅用于记录最终的效果,从0到1的实现过程后续进行补充,由于抢占式实例的云服务器按量进行每小时计费,为了避免持续的收费,所以我急 ...
最新文章
- 物理机_双机调试_资料
- jdbc驱动_JDBC概述和CRUD
- ubuntu下修改中文字体
- 2019年上半年总结__下半年计划
- lambda 和 std::function
- 两台服务器实现会话共享
- 重庆理工大学两江校区计算机学院,重庆理工大学两江校区国际项目9月开学
- java 编译class_.java文件怎样编译成.class文件,你值得一看的技巧
- 用JS实现简单的省市联动
- VBA自定义方法 快捷键设置
- java email 正则 验证
- 《线性代数及其应用》系列笔记
- 【python数据分析】亚太地区的商学院(商务与经济统计案例3-3)数据分析
- Red5流媒体服务器的搭建
- 字体如何设计,这几点很重要
- oracle 18c 转 11g,安装Oracle:Oracle 18c、Oracle 11g
- vue里 a(){} 和a:()=>{}的区别
- 银行外包Java开发的一些感想2023.2.5
- 区块链技术方向的就业前景
- python http服务器
热门文章
- 环信服务器发送消息,环信服务器发送消息
- CCF-CSP201809-4 再卖菜
- [论文阅读] Beyond part models: Person retrieval with refined part pooling
- php 七牛云获得上传token,客户端生成七牛上传token
- DQN:Playing Atari with Deep Reinfocement Learning
- Google文档初学者指南
- 微信小程序getUserProfile详解
- 沧小海基于xilinx srio核的学习笔记之第三章 xilinx srio核介绍(一)结构介绍
- mtr--- 网络诊断工具
- Android深入源码分析理解Aidl整体调用流程(雷惊风)