项目介绍
为了拓展高阶课的用户销量,目前通过BD与周边学校合作,开展四节体验课促销活动,并且会在第三节体验课后开展“高阶课程讲座”并开启高阶课的报名通道,目前项目已经完结,请根据已有的数据源分析并提出优化方案。
项目流程
- 用户行为路径轨迹
- 1.1 分析一般在线产品用户行为路径,并结合真实体验过程,绘制流程图
- 1.2 对数据源进行特征转换(将“是”,“否”转换为“1”,“0”),方便统计绘制漏斗图
- 1.3 漏斗图绘制
- 案例复盘
- 2.1 数据观察(去重、查看缺失值、查看数据大小及类型)
- 2.2 清洗数据(清洗杂乱学校名称字段、拆分课程报名情况)
- 2.3 数据合并(合并报名信息和上课情况表)
- 2.4 数据分析(从用户路径、学校、年级、推广渠道等维度展开分析)
1.用户行为路径轨迹
1.1 用户路径
用户体验产品路径一般为:渠道曝光->产生兴趣->信息采集->体验->完成
1.2 特征转换
为了方便读取数据以及统计各阶段人数,将数据第三列之后根据是、否进行特征转换为1,0
读取原始数据
# 读取excel文件
# 查看excel文件表格
wb = openpyxl.load_workbook("数据.xlsx")
wb.sheetnames
# 读取数据
df2 = pd.read_excel("数据.xlsx",sheet_name="上课数据")
特征转换:
dic = {"是":1,"否":0}
i = 0
for index in df2.columns:
i += 1
if i > 3:
df2[index] = df2[index].map(dic)
处理结果:- 文章一共有973条数据
1.3 绘制漏斗图
导入pyecharts绘制互动性可视化漏斗图
from pyecharts import options as opts
from pyecharts.charts import Funnel
c = ["总人数",'绑定微信','绑定手机号','添加老师','登录APP','第一节课完课',
'第一节课作业完成','第二节课完课','第二节课作业完成', '第三节课完课','第三节课作业完成',
'高阶课程点击数','高阶课程报名数','第四节课完课','第四节课作业完成']
c1 = [df2.ID.count(),df2["绑定微信"].sum(),df2["绑定手机"].sum(),df2["添加老师"].sum(),df2["登录APP"].sum(),
df2["第一节课是否完课"].sum() , df2["第一节课是否完成作业"].sum(),df2["第二节课是否完课"].sum() , df2["第二节课是否完成作业"].sum(),
df2["第三节课是否完课"].sum() , df2["第三节课是否完成作业"].sum(),df2["高阶课报名情况"].value_counts()["点击未报名"],df2["高阶课报名情况"].value_counts()["点击已报名"],
df2["第四节课是否完课"].sum() , df2["第四节课是否完成作业"].sum()]
c1 = [round(int(i)/973*100,2) for i in c1]
c = (
Funnel()
.add(
"转换率",
[list(z) for z in zip(c,c1)],
sort_="none",
label_opts=opts.LabelOpts(is_show=True, position="inside"),
tooltip_opts=opts.TooltipOpts(trigger="item", formatter="{a} <br/>{b} : {c}%"),
)
.set_global_opts(title_opts=opts.TitleOpts(title="流程转化",subtitle="计算方式:人数/总人数"),
legend_opts=opts.LegendOpts(pos_left='right',pos_top="90%"))
)
c.render_notebook()
2. 案例复盘
2.1 观察数据
检验缺失值:df1.info()
去重:df1.drop_duplicates()
# 检查是否缺失
df1.info()
# 判断是否有重复值
df1 = df1.drop_duplicates("id")
结果:删除2条重复字段后,共有968条数据,无缺失值
2.2 字段清洗
由于表单为自主填写,存在许多杂乱数据,需要进行清洗区分
2.2.1 学校字段:
df1.学校.unique()
经由业务部门沟通,先将学校分为以下7所:
- 邳州春田花花实验小学
- 十堰东风八零学校
- 北大附属西瓜小学
- 简阳春田花花小学
- 三亚第九小学
- 郑州第九十八中小学
- 肇庆第九小学
以下字段出现混淆: - 【江苏邳州市春田花花、】【简阳市春田花花小学】以及【春田花花小学】
- 【三亚第九小学】、【肇庆第九小学】以及【第九小学】
在数据清洗中,由于数据维度不够,将春田花花实验小学划为江苏邳州春田花花实验小学 ,不包含实验小学字样的划成简阳市春田花花小学。
将包含三亚的统一划为三亚第九小学 , 不包含三亚但是包含九小的划为肇庆市第九小学
def clean_school(b):
matchObj_baling = re.search( r'八零', b, re.M|re.I)
matchObj_xigua = re.search( r'西瓜', b, re.M|re.I)
matchObj_jiushiba = re.search( r'九十八', b, re.M|re.I)
matchObj_sanya = re.search( r'三亚', b, re.M|re.I)
matchObj_shiyan = re.search( r'实', b, re.M|re.I)
matchObj_chuntian = re.search( r'春田花花', b, re.M|re.I)
matchObj_jiuxiao = re.search( r'九小', b, re.M|re.I)
if matchObj_baling:
b = '湖北省十堰市东风八零学校'
elif matchObj_xigua:
b = '北大西瓜小学'
elif matchObj_jiushiba:
b = '郑州市第九十八中小学部'
elif matchObj_sanya:
b = '三亚市第九小学'
elif matchObj_shiyan:
b = '邳州市春田花花实验小学'
elif matchObj_shiyan == None and matchObj_chuntian: # 如果“邳州市春田花花实验小学”匹配失败,则进行简阳春天花花匹配
b = '简阳市春田花花小学'
elif matchObj_sanya == None and matchObj_jiuxiao:
b = '肇庆市第九小学'
return b
# 清洗
df1["学校"] = df1['学校'].map(clean_school)
2.2.2 其他字段
df1["年级"].unique()
df1["班级"].unique()
df1["三级渠道"].unique()
df2.高阶课报名情况.value_counts()
- 根据显示结果,发现均无异常字段,无需清洗
2.2.3 字段拆分
高阶课报名情况中,存在三种数据,“未点击进入”,“点击未报名”,“点击已报名”,为方便区分,利用pd.get_dummies将三种数据进行特征提取。
df2 = pd.concat([df2,pd.get_dummies(df2["高阶课报名情况"])],axis=1)
df2.drop("高阶课报名情况",axis = 1,inplace = True)
2.3 数据合并
将用户来源及信息表与用户上课信息表通过"ID"合并
- 注意:用户来源表中字段名称为“id”,上课信息表中字段名称为“ID”
data = pd.merge(df1,df2,left_on="id",right_on="ID")
# 空值检查
data.isnull().sum().sum()
# 删除多余字段
data.drop(["ID","电话号码","序号"],axis = 1,inplace = True)
2.4 数据分析
2.4.1 漏斗图绘制
参照开始流程,使用pyecharts进行漏斗图绘制
from pyecharts import options as opts
from pyecharts.charts import Funnel
c = ["总人数",'绑定微信','绑定手机号','添加老师','登录APP','第一节课完课',
'第一节课作业完成','第二节课完课','第二节课作业完成', '第三节课完课','第三节课作业完成',
'高阶课程点击数','高阶课程报名数','第四节课完课','第四节课作业完成']
c1 = [df2.ID.count(),df2["绑定微信"].sum(),df2["绑定手机"].sum(),df2["添加老师"].sum(),df2["登录APP"].sum(),
df2["第一节课是否完课"].sum() , df2["第一节课是否完成作业"].sum(),df2["第二节课是否完课"].sum() , df2["第二节课是否完成作业"].sum(),
df2["第三节课是否完课"].sum() , df2["第三节课是否完成作业"].sum(),df2["点击未报名"].sum(),df2["点击已报名"].sum(),
df2["第四节课是否完课"].sum() , df2["第四节课是否完成作业"].sum()]
c1 = [round(int(i)/973*100,2) for i in c1]
c = (
Funnel()
.add(
"转换率",
[list(z) for z in zip(c,c1)],
sort_="none",
label_opts=opts.LabelOpts(is_show=True, position="inside"),
tooltip_opts=opts.TooltipOpts(trigger="item", formatter="{a} <br/>{b} : {c}%"),
)
.set_global_opts(title_opts=opts.TitleOpts(title="流程转化",subtitle="计算方式:人数/总人数"),
legend_opts=opts.LegendOpts(pos_left='right',pos_top="90%"))
)
c.render_notebook()
结果:
- 从漏斗图得知,整体符合流程转换规则,不过登录APP到第一节课完课转换率较低
- 但在第四节课完课处开始出现异常,第四节课完课率比高阶课程报名数还要高,根据用户链路,没有报名的用户是不能开始第四节课的,这里可能出现数据错误,需要相关部门进行检查重新埋点
- 第二节课、第三节课作业完成率均比相应完课率较高,一部分同学没有听课直接做作业,推测可能是难度较低,可以适当提升难度
- 转换率在报名处最低,符合规则,但同样,需要调研用户原因,查看是什么原因导致报名数较低,价格原因还是其他原因
2.4.2 多维度统计分析
(1)整体:
(2)学校
grouped_school = data.groupby("学校").count()["id"].reset_index()
# 绘图
bar = (Bar()
.add_xaxis(list(grouped_school.学校))
.add_yaxis("参与人数",[int(i) for i in grouped_school.id.values])
.set_global_opts(title_opts=opts.TitleOpts(title = "各学校参与人数"),
xaxis_opts=opts.AxisOpts(name = "学校",axislabel_opts=opts.LabelOpts(rotate = 20)))
)
bar.render_notebook()
- 春田花花实验小学人数最多,东风八零次之
(3)三级渠道
grouped_bd_sc = data.groupby(["三级渠道","学校"]).count()["id"].reset_index()
数据导入PowerBI绘制桑基图- 主要渠道来源为周氏集团、武汉力公司、每日优鲜效果最好,河南公司和科技公司最次;
- 其中周氏集团和每日优鲜能够覆盖两所学校;
- 东风八零学校、春田花花实验学校的生源最多。
(4)年级与完课率
grouped_nianji = pd.concat([data.groupby("年级").sum().iloc[:,5:9],data.groupby("年级").sum()["点击已报名"]],axis = 1)
# 绘图
bar = (Bar()
.add_xaxis(grouped_nianji.columns.tolist())
.add_yaxis("幼儿园小班", grouped_nianji.loc['幼儿园小班'].tolist(), stack="stack1")
.add_yaxis("小学一年级", grouped_nianji.loc['小学一年级'].tolist(), stack="stack1")
.add_yaxis("小学二年级", grouped_nianji.loc['小学二年级'].tolist(), stack="stack1")
.add_yaxis("小学三年级", grouped_nianji.loc['小学三年级'].tolist(), stack="stack1")
.add_yaxis("小学四年级", grouped_nianji.loc['小学四年级'].tolist(), stack="stack1")
.add_yaxis("小学五年级", grouped_nianji.loc['小学五年级'].tolist(), stack="stack1")
.add_yaxis("小学六年级", grouped_nianji.loc['小学六年级'].tolist(), stack="stack1")
.add_yaxis("初中一年级",grouped_nianji.loc['初中一年级'].tolist(), stack="stack1")
.set_series_opts(label_opts=opts.LabelOpts(is_show=False),
axis_opts = opts.AxisOpts(
interval = None,
),
)
.set_global_opts(title_opts=opts.TitleOpts(title="完\n成\n课\n程\n及\n作\n业\n学\n员\n年\n级\n分\n布"
,padding = [150,100,5,10]),
xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=-15)),
)
)
bar.render_notebook()
- 每节课均是小学五年级占比最多,其次是小学三年级、小学四年级
- 幼儿园以及小学五年级以上,几乎没有人参与活动以及报名,推测可能是没有向这些年级的学生推广(幼儿园太小、六年级学生太忙等等)
2.4.3 特征工程处理
使用sklearn对于学校、年级、三级渠道字段进行特征处理,将至转换为数值型
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
data['学校'] = le.fit_transform(data['学校'])
data['年级'] = le.fit_transform(data['年级'])
data['三级渠道'] = le.fit_transform(data['三级渠道'])
正相关部分:第三节课是否完成作业与第四节课是否完成作业表现出强相关 ,高达0.87。第一次课程到第四次课程,可以看出他们关联性较大,可谓是环环相扣,呈现出了方块形状。
负相关部分:学校与三级渠道达到-0.35。
结论:
从登录APP到第一节课完课 ,用户流失较严重,需要对该部分用户进行调研 ,看是难度太大还是课程不能引起他们的兴趣。
第三节课作业完成到高阶课程报名这一过程 , 也出现数据异常,占比从60.8%下降到8%,但是第四节课的作业完成率与第四节课作业完成率都达到了百分之五十,甚至作业完成率高于完课率,这里要和产品部门沟通,对这里的用户浏览轨迹进行专项复盘,是不是数据埋点需要重新进行设计。
完成作业及课程的学员大多分布在小学三、四、五年级,幼儿园及小学六年级、初中一年级几乎没有,根据二八法则,建议花更多时间在小学三四五年级身上,进行高阶课程拓展。
逆转集团、河南公司、科技公司的投放效果有限,周氏集团与每日优鲜的覆盖效果较好,可以覆盖两个学校。建议后期选择周氏集团与每日优鲜。
根据真实体验情况,建议相关助教部门将发出的大量网址链接及视频教程,以小程序或者H5表单形式呈现,以及视频添加相关视频说明。减少一般用户对网址链接的抗拒感,增加品牌认知度。