提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
引用文本
项目背景
该数据集来源于2020年泰迪杯个人技能赛,其具体为某一教育平台的线上用户数据,包括用户登录信息、用户信息、用户学习记录表。2020年在新冠肺炎疫情冲击下,线上教育平台成为“互联网+教育”成果的重要发展领地,教育平台在此分析中,欲挖掘用户有关信息,分析用户流失情况,面向用户提供更优质的教育服务,同时反哺教育平台做大做强。数据链接分享:
(https://www.heywhale.com/mw/dataset/607cfa06f15a1d00171505e3)
1. 用户登录记录表(login表)基本信息
user_id | login_time | login_place |
---|---|---|
用户3 | 2018/9/6 9:32 | 中国广东广州 |
用户3 | 2018/9/7 9:38 | 中国广东广州 |
用户3 | 2018/9/7 9:57 | 中国广东广州 |
用户4 | 2018/9/8 19:42 | 中国福建福州 |
用户5 | 2018/10/6 9:32 | 中国江苏南京、 |
- login表:记录了用户从2018年9月6号产品上线以来的登录信息,同一用户同一天可有多条登录信息。
- 在平台角度,通过该表可深入分析平台的流量时间变化情况;
- 在用户角度,用户的登录频次、距今时长可反映用户的产品依赖水平、流失水平
2. 用户信息表(users表)基本信息
user_id | register_time | recently_logged | number_of_classes_join | number_of_classes_out | learn_time | school |
---|---|---|---|---|---|---|
用户44251 | 2020/6/18 9:49 | 2020/6/18 9:49 | 0 | 0 | 41.25 | |
用户44250 | 2020/6/18 9:47 | 2020/6/18 9:48 | 0 | 0 | 0 | |
用户44249 | 2020/6/18 9:43 | 2020/6/18 9:43 | 0 | 0 | 16.22 | |
用户44248 | 2020/6/18 9:09 | 2020/6/18 9:09 | 0 | 0 | 0 | 华南理工大学 |
- 数据说明:该用户信息表展示了用户的基础信息,包括注册时间、最近登录时间、加入的班级数、离开的班级数、平台学习时长以及用户所在学校等,user_id为唯一标识符,仅出现一次。
- 基于该信息,可了解用户的产品使用情况、学习时长、班级加入、是否填写学校等
3. 用户学习记录表(study_information表)基本信息
user_id | course_id | course_join_time | learn_process | price |
---|---|---|---|---|
用户3 | 课程106 | 2020/4/21 10:11 | width: 0% | 0 |
用户3 | 课程136 | 2020/3/25 11:44 | width: 12% | 0 |
用户3 | 课程205 | 2018/9/10 18:17 | width: 63% | 0 |
用户4 | 课程26 | 2020/3/31 10:52 | width: 0% | 319 |
用户4 | 课程34 | 2020/3/31 10:52 | width: 15% | 299 |
- 数据说明: 该表记录了用户加入课程的记录,包括课程编号、加入时间、至今学习进度以及课程价格
- 在用户角度: 可挖掘用户与课程之间的关系,得出用户的课程完播率、课程平均进度、消费水平等信息
- 在平台角度: 可挖掘最受用户喜欢的课程信息,通过用户的课程选择相似度,可向用户推荐个性化课程
二、数据预处理
0)导入包
import pandas as pd
import numpy as np
import datetime
from chinese_calendar import is_workday
import jieba
1.用户登录记录表(login表)数据预处理
1) 缺失值观测
login = pd.read_csv('login.csv',encoding = 'gbk')
login.info()
#没有缺失值
2)时间字段拆分
login['login_time'] = pd.to_datetime(login['login_time'])
login['date'] = login['login_time'].dt.date
login['time'] = login['login_time'].dt.time
login['month'] = login['login_time'].dt.month
login['day'] = login['login_time'].dt.day
login['hours'] = login['login_time'].dt.hour
login['weekday'] = login['login_time'].dt.weekday
## 对login中的'login_time'字段进行处理,提取出时间的各个维度:年份、月份、\
工作日、具体时刻,以便后续观测流量的对应时间分布情况
3)地区字段拆分
eg: 将”中国广东广州“拆分出国家、省份、地区三个维度; 此外,对来自其他国家地区的字段通过jieba进行智能拆分
for i in range(login.shape[0]):
if login.loc[i,'login_place'][0:2] == '中国':
login.loc[i,'国家'] = '中国'
if '黑龙江' in login.loc[i,'login_place']:
login.loc[i,'省份'] = '黑龙江'
if len (login.loc[i,'login_place'])>5:
login.loc[i,'地区'] = login.loc[i,'login_place'][5:]
else:pass
if '新疆维吾尔' in login.loc[i,'login_place']:
login.loc[i,'省份'] = '新疆维吾尔'
if len(login.loc[i,'login_place'])>7:
login.loc[i,'地区'] = login.loc[i,'login_place'][7:]
else:pass
if '内蒙古' in login.loc[i,'login_place']:
login.loc[i,'省份']='内蒙古'
if len(login.loc[i,'login_place'])>5:
login.loc[i,'地区']=login.loc[i,'login_place'][5:]
else:pass
else:
login.loc[i,'省份']=login.loc[i,'login_place'][2:4]
login.loc[i,'地区']=login.loc[i,'login_place'][4:]
else:
li = [word for word in jieba.cut(login.iloc[i,2])]
if len(li) == 2:
login.loc[i,'国家'] = li[0]
login.loc[i,'省份'] = li[1]
else:
login.loc[i,'国家'] = li[0]
if i%10000 == 0:
print(f"{round(i*100/(int(login.shape[0])),2)}%")
4) 深入挖掘信息: 由用户的登录信息可得到最近一次的登录信息,计算出距今非活跃天数
# 以最近的时间为基准,计算出用户每一次登录距离现在的时间
login['时间差1'] = pd.to_datetime(login['login_time']).max() - pd.to_datetime(login['login_time'])
login_time = dict(login.groupby('user_id').login_timt.max())
- 至此已将login表基本处理完毕,得到login表以及仅记录用户距今非活跃天数的login_time字典
2.用户信息表(users表)数据预处理
1)缺失值情况分析
users.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 43983 entries, 0 to 43982
Data columns (total 7 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 user_id 43916 non-null object
1 register_time 43983 non-null object
2 recently_logged 43983 non-null object
3 number_of_classes_join 43983 non-null int64
4 number_of_classes_out 43983 non-null int64
5 learn_time 43983 non-null float64
6 school 10571 non-null object
dtypes: float64(1), int64(2), object(4)
memory usage: 2.3+ MB
# 考虑到用户ID是用户的唯一标识,确实为缺失情况,而非正常可不填选项,且缺失的数据相对较少,因此删除数据。学校数据字段缺失严重,考虑为实际选填数据,暂时保留,并且创建是否填写学校信息
users = users[~users.user_id.isnull()]
# 将是否填写学校信息设置为0、1变量,作为后续可能有用的信息
users['是否填写学校信息'] = users['school']
users.是否填写学校信息[~users['是否填写学校信息'].isnull()]=1
users.是否填写学校信息[users['是否填写学校信息'].isnull()]=0
users.是否填写学校信息.value_counts()
2)异常值分析
- 可以看出有一些recently_logged时间和现在的时间很接近,有一些很远,因此可以将‘–’进行进一步分析
- 用户注册后未登录
- 用户注册后就未退出登录 使用login中的最新登录信息进行替换 因此考虑使用学习时间加上注册的时间作为其最近的登录时间,且设置一天学习8小时为上限
login_time = dict(login.groupby('user_id').login_time.max())
u_2 = users[users.recently_logged!='--']
u_1 = users[users.recently_logged=='--']
for i in range(u_1.shape[0]):
if u_1.iloc[i,0] in login_time.keys():
u_1.iloc[i,2] = pd.to_datetime(login_time[u_1.iloc[i,0]])
else:
if pd.to_datetime(u_1.iloc[i,1]) + datetime.timedelta(days = int(u_1.iloc[i,5])/480 ) > pd.to_datetime('2020-06-18'):
u_1.iloc[i,2] = pd.to_datetime('2020-06-18')
print('修改为最新时间')
else:
u_1.iloc[i,2] = pd.to_datetime(u_1.iloc[i,1])+datetime.timedelta(days = int(u_1.iloc[i,5])/480)
users = pd.concat([u_1,u_2])
3)数据提取: 各类时间差、加入的班级数,根据最近登录距今时间差划分活跃用户和非活跃用户
def str_datetime(df,column_name = 'login_time'):
df[column_name] = pd.to_datetime(df[column_name])
df[column_name] = df[column_name].apply(lambda x:x.strftime('%Y-%m-%d'))
return df
str_datetime(users,column_name = 'register_time')
str_datetime(users,column_name = 'recently_logged')
users['register_logged_time'] = pd.to_datetime(users['recently_logged']) - pd.to_datetime(users['register_time'])
users['register_now_time'] = pd.to_datetime(users['register_time']).max() - pd.to_datetime(users['register_time'])
users['logged_now_time'] = pd.to_datetime(users['recently_logged']).max() - pd.to_datetime(users['recently_logged'])
# 现在加入的班级的数量
users['number_of_classes_now'] = users['number_of_classes_join'] - users['number_of_classes_out']
users
# 确定用户活跃程度类型
def 确定用户类型(x):
if x > 90:
y = "流失用户"
elif x<=90 and x>60:
y = "潜水用户"
elif x<=60 and x>30:
y = "低活跃用户"
else:
y = "高活跃用户"
return y
users['用户类型'] = users['logged_now_time'].apply(lambda x:确定用户类型(x))
users.loc[stu_info1['用户类型']=='流失用户','是否流失'] = 1
users.loc[stu_info1['用户类型']!='流失用户','是否流失'] = 0
3.用户学习记录表(study_information表)数据预处理
1)缺失值+重复值处理
stu_info = stu_info.drop_duplicates()
stu_info.info()
# 缺失值查看,其中课程价格列存在缺失
<class 'pandas.core.frame.DataFrame'>
Int64Index: 194974 entries, 0 to 194973
Data columns (total 5 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 user_id 194974 non-null object
1 course_id 194974 non-null object
2 course_join_time 194974 non-null object
3 learn_process 194974 non-null object
4 price 190736 non-null float64
dtypes: float64(1), object(4)
memory usage: 8.9+ MB
2)查看课程价格情况
stu_info[stu_info.price.isnull()].course_id.value_counts()
课程51 4011
课程96 227
Name: course_id, dtype: int64
stu_course = stu_info.groupby(['course_id']).agg({'price':['max','min']})
stu_course[(stu_course['price']['max']-stu_course['price']['min'])!=0]
# 不存在差异定价,且51和96课程价格为nan,其中51和96课程共计4238条数据,暂时不做处理
3)同login表的时间处理方式相同,对stu_info时间列进行处理
- 最终依据user_id列将login表、stu_info表、以及users表进行合并. 进行后续分析
三、tableau进行数据分析
tableau为数据可视化工具,其将数据分为两类——度量型数据、维度型数据. 度量型数据描述数据的大小、规模、尺寸等信息,维度型数据描述数据的特点、个性、分布等定性信息,在图形中区分不同信息. 通过拖拽的方式,形成有轴图形或无轴图形.
1. 主题确定:教育平台用户流失水平
- 基于现有的三数据表,围绕教育平台用户流失水平主题进行分析,可拆解出以下问题:
- 了解教育平台现状:
- 教育平台用户登录流量现状如何
- 教育平台用户的分布特点
- 教育平台用户的流失用户占比
- 深入分析流失用户情况:
- 用户流失时间分布
- 用户类型(流失类型) 与 用户的行为属性(消费、完播率、学习时长等因素之间的关系)
- 了解教育平台现状:
2. 子主题分析一:教育平台现状
1) 教育平台用户登录流量现状
- 数据表:login表
- 图形类型:为表现登录流量的变化情况,进行对比、变化分析,可制作成折线图、面积图或柱状图
- 登录人数变化
- tableau操作:login_time 拖拽到列,度量值(计数)拖拽到行,标记区设为线
- 结果:该教育平台在2018年-2020年2月2日使用人数较少,但在2020年2月2日(疫情起始)后使用人数暴涨,在同年4月份回落,平台流量没有良好的留存水平,需要深入分析用户留存率低的原因。
- 每日登录分布
- tableau操作:login表中"hours"列设定为度量型数据(目的为分组聚合), 并拖拽至列,度量值(计数)拖拽至行,标记区设标记为"区域”
- 结果: 在该平台中,用户集中在三个时间段登录,上午9:00-11:00,下午14:00-17:00,晚上20:00-21:00三个高峰.
- 建议: 在线教育平台可在该时间段加强系统维护,保证课程流畅度。可在该时间段多植入相关课程广告以及相关课程销售活动,以此留住更多客户。
- 工作日登录人数对比分析
- tableau操作: login表中"weekday"列设定为度量型数据(目的为分组聚合), 并拖拽至列,度量值(计数)拖拽至行,标记区设标记为“条形图”
- 结果:在区分工作日和非工作日时,工作日的登录人数整体大于非工作日的登录人数,这符合学生的学习习惯。
2) 教育平台用户的分布特点
- 数据表:login表为主表, users表以user_id列与主表进行连接
- 图形类型:为表现教育平台用户的分布特点,可使用饼图、树立图等
- 登录人数的省份分布
- tableau操作: 标记区中放入"省份"(维度型变量),放入"计数(sheet)"(度量型变量),标记设为“饼图”
- 结果: 教育平台的基本盘在广东地区,需要在广东、湖北、河南、贵州等地区多开展营销活动,巩固基本盘。
- 登录人数的地区分布
- 在登录人数最多的前四大省份中探索登录人数的地区分布情况
- taleau操作: 设置筛选器,依据"省份"仅提取广东、湖北、河南、贵州四大省份,“地区”(维度型变量)放入“列”,行放入"计数(sheet)"(度量型变量),标记设为“线”
- 结果: 了解教育平台的地区分布情况,不仅仅在各省的省会有大量的用户,由各个重点省市地区的分布情况来看,可以看出各个省市中都存在一个或两个重点地区,如武汉、贵阳、广州、周口和郑州等地。该地区的存在使得省份的占比数据大幅提升。因此,后续在进一步的细分研究中,可以对以上地区进行重点调查。
3) 教育平台用户的流失用户占比
- 数据表:以users表为主表,users 表中已依据用户的最近一次登录时间距今时长对用户的类型进行划分。其中最近一次登录时间差大于90天定义为“流失用户”,在60天至90天之间定义为“潜水用户”,在30天至60天之间定义为“低活跃用户”,在30天以内定义为高活跃用户。
- tableau操作: 标记区放入“用户类型”(维度型数据)和(计数:user_id)度量型数据,标记设为“饼图”
- 结论: 该平台在2年的运营时间内,积累了大量的流失用户,由于平台刚刚起步,正值窗口期,需要对流失用户的流失原因进行分析,并加以改进。
2. 子主题分析二:深入分析流失用户情况
- 数据集:基于user表、stu_info表等
1)用户流失时间、地区情况
- 流失时间热力图
- python操作: 根据users表中的流失时间划分为"大于150天"、“大于90天"等等 , 生成变量"流失时间划分”
- tableau操作:“流失时间划分”(维度变量)放于列,“省份”(维度变量)放于行, “计数user_id”放于标记区,标记设置为“方型”,同时为 “计数user_id”赋予“颜色”属性,即可根据计数大小给予不同的颜色深度区分。
- 结果:从地区角度,广东地区流失人数较多,此次是北京、湖北、上海、江苏等,需对重点地区进行相关的用户召回营销。
2) 用户类型(流失类型) 与 用户的行为属性(消费、完播率、学习时长等因素之间的关系)
- 用户类型下的消费与学习进度散点图
- tableau操作: 平均值_learn Process(度量型变量)放入列,平均值_price(度量型变量)放入行,同时将“用户类型”放于标记区,设置为“形状”即可
- 结果: 区分不同的用户类型时,随着活跃水平的上升,用户的平均学习进度和平均课程消费是逐步上升的。活跃水平高的用户,其线上课程参与深度是相对更高的,愿意花费资金购买线上课程,更有耐心观看线上课程。其次“学习进度”可以视为代表用户的体验感受水平的指标之一,只有课程质量好,用户愿意看,其学习进度水平才会高。进而提出猜测:用户的体验感受水平越好, 其学习进度水平更高,其消费意愿更充分,消费金额与学习进度之间可能存在正相关关系。
- 流失率与学习进度关系
- python操作:uses表将已将用户定义成各类用户类型, 故而将用户类型为"流失用户"的标为“1”, 非流失用户的标为0,生成“是否流失”列
- tableau操作: 将平均值Learn Process(度量型变量)放在列上,平均值"是否流失"(度量型变量)放在行上,将“省份”(维度型变量)放在标记区上,并用"颜色"加以区分
- 结果:
- 从散点图可以看到,流失率与学习进度呈现负相关关系。随着流失率的上升,用户的学习进度为下降的趋势。一方面可能因为太多低学习进度的流失用户拉低省份的学习进度水平,另一方面也可能反映了流失率与学习进度水平之间的关系,正如前面所说的学习进度代表着用户的体验感受,体验感受低的自然流失水平高。
- 从地区角度:其中我们可以看到“北京、天津、香港、上海”等教育资源丰富的地区流失度比较高,也可能推测出线下教育资源丰富的地区可能并非教育平台的首要推广用户,而教育资源相对差的比如“宁夏、贵州、广西”等省份可能更需要线上教育资源对其进行补充,该地区的用户有更多的线上课程需求。
- 消费与学习进度之间的关系
- tebleau操作: 将平均值_price放在列上, 将平均值Learn Process放在行上, “省份”放在标记区上,同时标记设为"形状"
- 结果: 消费与学习进度之间呈正相关, 用户的累计消费金额随学习进度的提升而提升。一方面。学习进度意味着用户体验水平,体验水平上升带动消费水平上升,另一方面,付了费的课程可能会更注重课程的学习进度。
- 课程价格与学习进度关系
- tableau操作: 将课程价格price修改成“维度型变量”,将其放于列中,平均值LearnProcess放于行中,标记为"线"。
- 结果:随着价格水平的上升,用户的平均学习进度波动逐渐增大。花费了较大金额,但用户的学习进度在50%下的情况偶有出现。一旦付费课程质量不高,用户花了钱却不忍浪费继续观看时,用户体验水平会断崖式下跌。因此,需要注重用户的付费课程学习感受。
四、报表分析
1. 项目总结
本项目基于某教育平台的用户登录信息、用户个人信息以及用户课程学习记录三信息表,挖掘了平台流量以及用户流失等信息。使用python对数据进行预处理,使用tableau进行数据可视化分析。最终得出以下基本结论:
- 该教育平台正值窗口期,平台流量没有良好的留存水平,但有良好的发展趋势,需要深入分析用户留存率低,做好招新促活营销。
- 该教育平台的基本盘在广东、湖北、河南、贵州等省份,线上教育的潜在用户可能更多分布在线下教育资源不充足、受疫情影响更为严重的地区。
- 该教育平台两年间的用户流失率水平较高,在78.3%左右,分析用户的流失率与用户的行为属性之间的关系,比如消费、学习进度等。其中学习进度指标可视为教育平台的关键指示指标之一,与流失率、消费金额等息息相关。
- 基于以上结论,认为教育平台的招新促活营销可从以下方面展开:
- 重点省份、地区开展教育平台招新促活活动,同时不忽视线下教育资源差但网络基础设施完善的地区的平台推广
- 在用户的重点使用时段做好平台维护,保障用户的使用感受
- 平台运营活动以“用户的学习进度”为关键指示指标,用来评估各类运营活动的运营成效
- 为提高用户的“学习进度”指标,因开展、上传更多的、高质量教育资源,实打实的帮助用户学习。