[Python]RFM用户分类模型, 加matplotlib可视化数据--在线教育行业分析案例连载1


前言

该文章为连载的第一篇:RFM用户分类模型

某家在线教育机构拥有自己开发的教育产品VLE,该教育机构提供了他们四个学期里,开展的七门课的数据,接下来我会根据这些数据,为该教育机构做一系列的数据分析,包括用户的RFM模型、用户分群特征、用户成绩分析等等。

该教育机构部分数据库结构如下

在这里插入图片描述


如下这一篇文章为:用户的RFM模型

先简单介绍一下RFM模型:

RFM模型是衡量客户价值和客户创利能力的重要工具和手段。
该机械模型通过一个客户的

  1. 近期购买行为(R:Recency)、
  2. 购买的总体频率(F:Frequency)
  3. 花了多少钱(M:Monetary)

3项指标来描述该客户的价值状况。


该案例是在线教育产品,并且这里只提供用户一学期购买课程的消费注册使用情况,所以RFM会调正为:

  1. 近期产品使用行为(R:Recency)、
  2. 产品使用频率(F:Frequency)
  3. 花了多少钱(M:Monetary)

这个案例中计算用户RFM模型会用到:

  1. studentRegistration 学生注册信息表 (记为regi)
  2. studentVle 学生产品交互行为表 (记为vle)
  3. courses 课程表 (记为courses)

其中:

  1. code_presentation为学期
  2. code_module为课程
  3. 其他字面意思比较好理解

一、导入库

import pandas as pd
import numpy as np
import datetime
import time
import matplotlib
matplotlib.rcParams['font.sans-serif'] = ['Arial Unicode MS']
matplotlib.rcParams['axes.unicode_minus']=False
import matplotlib.pyplot as plt
import seaborn as sns
import sklearn
from sklearn.preprocessing import LabelEncoder
np.set_printoptions(suppress=True)
pd.set_option('display.float_format', lambda x: '%.4f' % x)


二、构造价格数据

因为这里没有关于价格的数据,我们需要对每门课构造一个价格

构造价格的依据:

  • 假设AAA是最简单的课程课程难度随着AAA、BBB、CCC递增,价格会越来越贵
  • 假设课程价格的基准是10*时间长度,同时价格根据难度增加,BBB为11乘时间长度,CCC为12,以此类推
  • 同时物价膨胀学校每年也会调整增10%的学费

实现代码如下(示例):

presentation=sorted(courses["code_presentation"].unique().tolist())
#presentation 为['2013B', '2013J', '2014B', '2014J']
module=sorted(courses["code_module"].unique().tolist())
#module 为['AAA', 'BBB', 'CCC', 'DDD', 'EEE', 'FFF', 'GGG']

这里需要注意的是,不是每一学期都会开展这七门课


#基准价格
x=10
module_price={}
for m in module:
    module_price[m]=x+module.index(m)
    
#module_price 为{'AAA': 10, 'BBB': 11, 'CCC': 12, 'DDD': 13, 'EEE': 14, 'FFF': 15, 'GGG': 16}

#增加价格列,并用每门课基准价格乘时间长度
courses["price"]=courses["code_module"].map(module_price)
courses["price"]=courses["module_presentation_length"]*courses["price"]

#从第二学期开始,价格上升10%
for pre in presentation[1:]:
    courses.loc[(courses["code_presentation"]==pre),"price"]*=(1.1)**(presentation.index(pre))

courses.sort_values(by=["code_presentation","code_module"]).head(10)

在这里插入图片描述

三、分别计算RFM信息

这里我们只选取最新的一个学期2014J计算

1、聚合所需要的信息

代码如下(示例):

#聚合【学生注册信息表】和【学生vle交互信息表】,筛选出这一学期的

#用how="outer"的原因是部分学生注册了但没有使用VLE
regi_vle_this_pre=pd.merge(regi[regi["code_presentation"]=="2014J"],vle[vle["code_presentation"]=="2014J"],on=["code_module","code_presentation","id_student"],how="left")

#并对注册但没有使用过产品的用户,点击数调整成0
regi_vle_this_pre["sum_click"]=regi_vle_this_pre["sum_click"].fillna(0)
regi_vle_this_pre[regi_vle_this_pre["sum_click"].isna()]

#再聚合【课程表】
df=pd.merge(regi_vle_this_pre,courses[courses["code_presentation"]=="2014J"][["code_module","price"]],on="code_module")

在这里插入图片描述

2、计算每个学生的购买课程总价

这学期有10670学生,大部分学生都只买了一门课,有586人买了两门课,2人买了3门课,具体计算先忽略。

amount=pd.crosstab(df["id_student"],df["code_module"],values=df["price"],aggfunc="mean").fillna(0).reset_index()

amount["total_amount"]=amount["AAA"]+amount["BBB"]+amount["CCC"]+amount["DDD"]+amount["EEE"]+amount["FFF"]+amount["GGG"]

amount.sort_values(by="total_amount",ascending=False)

在这里插入图片描述

#将总价也聚合到上面的表里
df=pd.merge(df,amount[["id_student","total_amount"]],on="id_student")

3、计算RFM各指标

对各项指标,去查看一个描述统计值,并用箱线图查看异常值是否较多,再定义怎么去界定RFM高低的界限。

3.1 R

df.groupby("id_student").agg({"date":"max"}).describe(percentiles=[.25,.5,.75,.8])


date_list=[x for x in df.groupby("id_student").agg({"date":"max"})["date"].values.tolist() if str(x)!="nan" ]
#去掉nan值

plt.boxplot(x=date_list)
plt.show()

在这里插入图片描述
date这里最大是开课后有269天,最小的是开课前25天,这里假设每门课的开课时间一致,现在就是开课后269天,我们拿到的数据都是更新的。

这里去定义7天内使用过的才算近期使用,即269-7=262以上为R近用户

3.2 F

df.groupby(["id_student"]).agg({"date":pd.Series.nunique}).describe(percentiles=[.25,.5,.75,.8])

plt.boxplot(df.groupby(["id_student"]).agg({"date":pd.Series.nunique})["date"].values)
plt.show()

在这里插入图片描述
中位数和平均数相差加大,呈左偏态分布
大多数用户使用次数较低,但有少部分用户使用次数异常高,拉高平均值

这里暂时取中位数值作为F的临界点,即42天。

3.3 M

df.groupby(["id_student"]).agg({"total_amount":"mean"}).describe(percentiles=[.25,.5,.75,.8])

plt.boxplot(df.groupby(["id_student"]).agg({"total_amount":"mean"})["total_amount"].values)
plt.show()

在这里插入图片描述

平均数比中位数略高,有部分偏高异常值,原因是

  • 学生报名情况:这学期有10670学生,大部分学生都只买了一门课,有586人买了两门课,2人买了3门课
  • 课程价格情况:
    在这里插入图片描述

这里定义M高用户为选择课程价格为大于4500的用户

3.5 计算每个用户的RFM

回顾一下定义RFM各指标为高的界限:

  1. 前7天内有在使用产品为R高
  2. 在这学期中,使用产品超过42天为F高
  3. 购买价格课程大于4500为M高
df["cnt_use_day"]=df["date"]
rfm_df=df.groupby("id_student").agg({"date":"max","cnt_use_day":pd.Series.nunique,"total_amount":"mean","date_unregistration":"max"}).reset_index()


rfm_df["r"]=rfm_df["date"].apply(lambda x:1 if x>=262 else 0)
rfm_df["f"]=rfm_df["cnt_use_day"].apply(lambda x:1 if x>=42 else 0)
rfm_df["m"]=rfm_df["total_amount"].apply(lambda x:1 if x>=4500 else 0)

rfm_df["user_label"]=np.nan

RFM的标签分层(按RFM顺序):
(1,1,1)重要价值用户
(0,1,1)重要唤回客户
(1,0,1)重要深耕客户
(0,0,1)重要挽回客户
(1,1,0)潜力客户
(1,0,0)新客户
(0,1,0)一般维持客户
(0,0,0)流失客户

rfm_df.loc[(rfm_df["r"]==1)&(rfm_df["f"]==1)&(rfm_df["m"]==1),"user_label"]="重要价值用户"
rfm_df.loc[(rfm_df["r"]==0)&(rfm_df["f"]==1)&(rfm_df["m"]==1),"user_label"]="重要唤回用户"
rfm_df.loc[(rfm_df["r"]==1)&(rfm_df["f"]==0)&(rfm_df["m"]==1),"user_label"]="重要深耕用户"
rfm_df.loc[(rfm_df["r"]==0)&(rfm_df["f"]==0)&(rfm_df["m"]==1),"user_label"]="重要挽回客户"
rfm_df.loc[(rfm_df["r"]==1)&(rfm_df["f"]==1)&(rfm_df["m"]==0),"user_label"]="潜在用户"
rfm_df.loc[(rfm_df["r"]==1)&(rfm_df["f"]==0)&(rfm_df["m"]==0),"user_label"]="新用户"
rfm_df.loc[(rfm_df["r"]==0)&(rfm_df["f"]==1)&(rfm_df["m"]==0),"user_label"]="一般维持客户"
rfm_df.loc[(rfm_df["r"]==0)&(rfm_df["f"]==0)&(rfm_df["m"]==0),"user_label"]="流失用户"

rfm_df["user_label"].value_counts()

结果如下:
在这里插入图片描述

可视化:

plt.figure(figsize=(5,5))
cmap = plt.get_cmap("tab20c")
outer_colors = cmap(np.arange(8)*1)
#print(outer_colors)

data = rfm_df["user_label"].value_counts().sort_index().values.tolist()
label=rfm_df["user_label"].value_counts().sort_index().index.tolist()
 
#突出重要价值用户
plt.pie(data,pctdistance=0.7,autopct='%.1f%%',explode=(0,0,0,0,0.3,0,0,0),labels=label,colors=outer_colors)

plt.axis('equal')
plt.tight_layout()

plt.show()

在这里插入图片描述

同时这里我们有用户注册后注销的信息(date_unregistration),我们也可以看注销账号的用户里的用户分类:

rfm_df[rfm_df["date_unregistration"]>0]["user_label"].value_counts()

在这里插入图片描述


总结

从以上RFM信息看出,流失用户、一般维持用户占比较大,需要结合其他信息,做好精细化运营,促进学生使用产品,提升用户粘性。

同时在注销账号的用户中可以看到,注销用户较多,大约占25%,并且不少为R低F低M高的重要挽回用户,需要重点找到原因。

当我们拥有用户RFM标签,我们可以:

  1. 结合courses【课程表】去看是否有哪一门课的课程对用户吸引较大,能让用户持续使用产品
  2. 结合studentInfo【学生信息表】去重要价值用户有什么样的共性,比如重要价值用户中,多数学生为非贫困地区用户,某个年龄段的高频使用用户较多
  3. 结合studentAssessments【学生平时成绩表】去看流失用户、重要挽回用户有什么样的特征,是否他们的成绩较差而选择放弃使用,是否需要调正课程难度,评分标准
相关推荐
<p> <span> </span> </p> <p class="ql-long-32569780" style="font-size:11pt;color:#494949;"> <span style="color:#E53333;">92讲视频课+16大项目实战+课件源</span><span style="color:#E53333;">码+讲师社群闭门分享会</span> </p> <p style="font-size:11pt;color:#494949;">   </p> <p class="ql-long-32569780" style="font-size:11pt;color:#494949;"> <strong class="ql-size-14 ql-author-32569780"><span style="color:#337FE5;font-size:14px;">为什么学习数据分析?</span></strong> </p> <p class="ql-long-32569780" style="font-size:11pt;color:#494949;"> <strong class="ql-size-14 ql-author-32569780"><span style="color:#337FE5;"><br /> </span></strong> </p> <p class="ql-long-32569780" style="font-size:11pt;color:#494949;">       人工智能、大数据时代有什么技能是可以运用在各种行业的?数据分析就是。 </p> <p class="ql-long-32569780" style="font-size:11pt;color:#494949;"> <br /> </p> <p class="ql-long-32569780" style="font-size:11pt;color:#494949;">       从海量数据中获得别人看不见的信息,创业者可以通过数据分析来优化产品,营销人员可以通过数据分析改进营销策略,产品经理可以通过数据分析洞察用户习惯,金融从业者可以通过数据分析规避投资风险,程序员可以通过数据分析进一步挖掘出数据价值,它和编程一样,本质上也是一个工具,通过数据来对现实事物进行分析和识别的能力。不管你从事什么行业,掌握了数据分析能力,往往在其岗位上更有竞争力。 </p> <p style="font-size:11pt;color:#494949;">  <span style="font-size:11pt;"> </span> </p> <p class="ql-long-32569780" style="font-size:11pt;color:#494949;"> <span style="color:#337FE5;"><strong>本课程共包含五大模块:</strong></span> </p> <p class="ql-long-32569780" style="font-size:11pt;color:#494949;"> <strong class="ql-size-14 ql-author-32569780"><span style="color:#337FE5;"><br /> </span></strong> </p> <p class="ql-long-32569780" style="font-size:11pt;color:#494949;"> <strong class="ql-size-12 ql-author-32569780">一、先导篇:</strong> </p> <p class="ql-long-32569780" style="font-size:11pt;color:#494949;"> <span class="ql-author-32569780">通过分析数据分析师的一天,让学员了解全面了解成为一个数据分析师的所有必修功法,对数据分析师不在迷惑。</span> </p> <p style="font-size:11pt;color:#494949;">   </p> <p class="ql-long-32569780" style="font-size:11pt;color:#494949;"> <strong class="ql-size-12 ql-author-32569780">二、基础篇:</strong> </p> <p class="ql-long-32569780" style="font-size:11pt;color:#494949;"> 围绕Python基础语法介绍、数据预处理、数据可视化以及数据分析与挖掘......这些核心技能模块展开,帮助你快速而全面的掌握和了解成为一个数据分析师的所有必修功法。 </p> <p style="font-size:11pt;color:#494949;">   </p> <p class="ql-long-32569780" style="font-size:11pt;color:#494949;"> <strong class="ql-size-12 ql-author-32569780">三、数据采集篇:</strong> </p> <p class="ql-long-32569780" style="font-size:11pt;color:#494949;"> <span class="ql-author-32569780">通过网络爬虫实战解决数据分析的必经之路:数据从何来的问题,讲解常见的爬虫套路并利用三大实战帮助学员扎实数据采集能力,避免没有数据分析的尴尬。</span> </p> <p style="font-size:11pt;color:#494949;">   </p> <p class="ql-long-32569780" style="font-size:11pt;color:#494949;"> <strong class="ql-size-12 ql-author-32569780">四、分析工具篇:</strong> </p> <p class="ql-long-32569780" style="font-size:11pt;color:#494949;"> <span class="ql-author-32569780">讲解数据分析避不开的科学计算库Numpy、数据分析工具Pandas及常见可视化工具Matplotlib。</span> </p> <p style="font-size:11pt;color:#494949;">   </p> <p class="ql-long-32569780" style="font-size:11pt;color:#494949;"> <strong class="ql-size-12 ql-author-32569780">五、算法篇:</strong> </p> <p class="ql-long-32569780" style="font-size:11pt;color:#494949;"> <span class="ql-author-32569780">算法是数据分析的精华,课程精选10大算法,包括分类、聚类、预测3大类型,每个算法都从原理和案例两个角度学习,让你不仅能用起来,了解原理,还能知道为什么这么做。</span> </p> <p> <img alt="" src="https://img-bss.csdnimg.cn/202006110958102443.jpg" /> </p>
©️2020 CSDN 皮肤主题: 1024 设计师:白松林 返回首页