python猿辅导_如何用数据分析方法剖析“猿辅导”K12课程
前言
本次分析只是用猿辅导的案例来分享数据分析的思路和方法论。禁止将分析结果用于任何商业目的以及非法行为,若引起法律纠纷后果自负。同时声明数据来源与猿辅导官网关键指标数据未必真实。
概述
笔者将通过以下环节展示整个分析的过程。
涉及知识:
结构化思维,描述性分析,相关性分析,python爬虫,数据清洗 , mysql , 数据可视化
分析流程:
第一部分 : 定义目标
数据分析的第一步也是最关键的一步,就是“如何将一个命题转化拆分为一个可用数据分析的问题”,
笔者这里分享一下笔者的分析思路。
1.1 思考命题
命题: 分析猿辅导的课程
问1:为什么要分析这个命题?可以解决什么问题?带来多大价值?
答:这个问题的答案可能来自老板,来自需求方,来自自己;不管来源如何,都要审视命题本身是不是伪命题。
从本案例来说,笔者的分析的目的在于猿辅导是K-12教育的“独角兽”公司,目前已经E轮。对其公司“输出内容”的分析可以帮助笔者更深入的挖掘“在线辅导”业务的用户群体 分布,主要营收分布,学科分布;今后还可以通过分析其他同行业的公司进行对比分析。进而深入笔者对教育行业的理解,提高高人影响力。
问2:因变量Y是什么,自变量X是什么?
答:本案例中开始只是个抽象的命题:对猿辅导的课程进行分析,因变量Y应该是猿辅导的”辅导课“,那么辅导课可以拆解哪些属性呢?(老师,学生,时间,价格,类型,学段,年级,学科.......),这些元素是否可以被数据化呢?很明显是可以的。
问3:Y,X在哪?我可以从哪些渠道获得它们?
答:我们看一下猿辅导的官网,这些信息都是可以找到的,那么笔者可以判断,这个命题是一个数据可分析的问题
1.2 结构化拆分命题
这里要考验一个分析师数据分析思维的环节,同样的数据从不同维度拆分,同样的维度选择不同的嵌套关系分析结果的深度,颗粒度,层次和价值可能会大不相同。
笔者采用“金字塔原理”将可量化的问题结构化的产出。分为描述性分析和相关性分析。
1.2.1描述性分析
描述性分析本质上就是像画肖像一样,去描述你要表达的事物。这里的描述笔者采用的是“数据分布”概念,(关于数据分布和统计学概念可以参考笔者另一篇文章《深入浅出统计学》---木南的书,可以帮助初学者快速建立统计学的知识架构。)
问:哪些维度是最关键的指标?
答:这个问题考验的是一个分析师对某个领域或者行业的经验。笔者2年的教育行业的经验,选择以下四个指标作为分析对象:“课程”,“用户”,“师资”,“营收”。
1.2.2相关性分析
相关性分析是找出数据和数据之间的相关关系。 将总营收分解为课程价格和报名人数的乘积。
报名人数越多整体收入也就越多。那么报名人数受那些因素影响,每个因素影响的权重如何呢?这里需要进行相关性分析来回答这些问题。
同样也是根据经验,笔者认为以下四个因素可能会影响一个课程的报名人数,“年级”,“学科”,“单价”,“时长”。(其实还有重要因素“老师”,官网的数据过于有广告成分,会造成数据失真,笔者不做探讨)
第二部分 : 数据获取
数据获取的第一个问题要确定获取什么作为数据?这里如果第一步做的很到位那就很简单了,答案就是第一部分脑图中最末端的分支项。(课程,学科,年级,老师,价格,报名学生数)。
确定了要获取哪些数据后,我们来观察一下目标网站的层级结构。
需要爬取的元素
爬虫层级结构
爬虫思路
分析url有3个变量,学段,年级,学科。一共有72总组合,也就是72个不同的url,每个url有若干个对应的课程。爬虫是进行72次url的爬取,然后将对应的学段,年级,学科字段分配到对应的课程上。课程信息爬取名称,时间,老师,报名人数,价格等这些字段,然后汇总成一个表格嵌套字典的结构备用。其中老师的信息单拿出一个列表,并且每个老师有对应的课程id,用于和课程信息表相关联。最后输出两个excel,一个是课程列表,一个是老师列表。
爬虫代码
import requests
import json
import xlwt
import pandas as pd
listxueduan=['xiaoxue','chuzhong','gaozhong']
listgrade=['1','2','3','4','5','6','7','8','9','10','11','12']
list_c_1=['2','3','201']
list_c_2=['1','2','3','4','5','6','7','8','14']
list_c_3=['1','2','3','4','5','6','7','8','9']
lesson = []
teacher = []
def get_key_value(info_dict,k,j):
try:
info_dict[k] = j[k]
except KeyError as e:
for j_key in j:
if isinstance(j[j_key], dict):
get_key_value(info_dict,k,j[j_key])
list=[]
list11=[]
list12=[]
list13=[]
urllist=[]
for i in listxueduan:
if i=='xiaoxue':
for j1 in range(1,7):
#print(j1)
g=j1
for c1 in list_c_1:
c=c1
url = 'https://www.yuanfudao.com/tutor-student-lesson/api/homepage?_productId=374&platform=www&version=5.11.0&UDID=4d27a58f757db800e339317f1c245223×tamp=1532658211041&startCursor=0&limit=18&grade='+str(g)+'&channelId='+str(c)+'&studyPhase='+str(i)+'&withNextGrade=false'
urllist.append(url)
list11.append(i)
list12.append(j1)
list13.append(c1)
elif i=='chuzhong':
for j2 in range(7,10):
#print(j2)
g=j2
for c2 in list_c_2:
c=c2
url = 'https://www.yuanfudao.com/tutor-student-lesson/api/homepage?_productId=374&platform=www&version=5.11.0&UDID=4d27a58f757db800e339317f1c245223×tamp=1532658211041&startCursor=0&limit=18&grade='+str(g)+'&channelId='+str(c)+'&studyPhase='+str(i)+'&withNextGrade=false'
urllist.append(url)
list11.append(i)
list12.append(j2)
list13.append(c2)
else :
for j3 in range(10,13):
#print(j3)
g=j3
for c3 in list_c_3:
c=c3
url = 'https://www.yuanfudao.com/tutor-student-lesson/api/homepage?_productId=374&platform=www&version=5.11.0&UDID=4d27a58f757db800e339317f1c245223×tamp=1532658211041&startCursor=0&limit=18&grade='+str(g)+'&channelId='+str(c)+'&studyPhase='+str(i)+'&withNextGrade=false'
urllist.append(url)
list11.append(i)
list12.append(j2)
list13.append(c3)
study_dict={
'studyPhase':list11,
'grade':list12,
'channelId':list13
}
def main():
for i in range(0,72):
url = urllist[i]
s1=study_dict['studyPhase'][i]
s2=study_dict['grade'][i]
s3=study_dict['channelId'][i]
r = requests.get(url)
json_r= r.json()['list']
for j in json_r:
info_dict={
'studyPhase':s1,
'grade':s2,
'channelId':s3,
'id': None,
'minPrice': None,
'maxPrice': None,
'name': None,
'soldCount': None,
'price':None,
'subName': None,
'teachers':None
}
for k in info_dict:
get_key_value(info_dict,k,j)
print(info_dict)
lesson.append(info_dict)
for t in j['teachers']:
teacher_dict={
'lessonid':info_dict['id'],
'id':t['id'],
'nickname':t['nickname'],
'avatar':t['avatar']
}
teacher.append(teacher_dict)
work=xlwt.Workbook() #创建excel
sheet1=work.add_sheet('sheet1',cell_overwrite_ok=True) #创建sheet
head=['studyPhase','grade','channelId','id','minPrice','maxPrice','name','soldCount','price','subName']
y=0
for item in head: #编辑表头
sheet1.write(0,y,item)
y+=1
x=1
#用data做例子,实际操作用网页爬出的数据
for item in lesson:
if isinstance(item,dict):
for head_item in head:
if head_item in item.keys():
y=head.index(head_item)
sheet1.write(x,y,item[head_item])
x+=1
work.save('猿辅导课程表new2.xls')#保存
work2=xlwt.Workbook() #创建excel
sheet1=work2.add_sheet('sheet1',cell_overwrite_ok=True) #创建sheet
head2=['lessonid','id','nickname','avatar']
y=0
for item in head2: #编辑表头
sheet1.write(0,y,item)
y+=1
x=1
#用data做例子,实际操作用网页爬出的数据
for item in teacher:
if isinstance(item,dict):
for head_item in head2:
if head_item in item.keys():
y=head2.index(head_item)
sheet1.write(x,y,item[head_item])
x+=1
work2.save('猿辅导老师表new2.xls')#保存
if __name__ == '__main__':
main()
爬行结果
lesson表(清洗前)
一共225条课程数据
表头字段名:
学段,年级,课程类别id,课程ID ,最低售价,最高售价,课程名,报名数,售价,老师名,标签名
teacher表(清洗前)
一共465条老师数据(同一门课可能多名老师带,一名老师可能上多门课)
表头字段名:
课程ID ,老师ID,老师名,老师头像
第三部分 : 数据清洗
3.1 一次数据清洗 ---python
case1 --- 将价格赋值
当price列数据为0的时候,minprice和maxprice是有价格数据的,因此当price为0时候,将maxprice价格赋值给price,代码如下:
mport pandas as pd
str1='C:\\Users\\wnapple\\Desktop\\猿辅导课程表new2.xls'
str2='C:\\Users\\wnapple\\Desktop\\猿辅导老师表new2.xls'
lessondf = pd.read_excel(str1)
teacherdf = pd.read_excel(str2)
#print(p1)
s3 =lessondf.shape
#print(lessondf)
'''
数据清洗---价格赋值
'''
for i in range(0,225):
p1 =lessondf.loc[i,'price']
print(p1)
if p1==0:
p1=lessondf.loc[i,'maxPrice']
lessondf['price'][i]=p1
lessondf['price'].fillna(0,inplace=True)
case2 --- 将subname列中日期和年级字段拆分
将subname标签中的日期信息和年级信息拆分,分别变成两列,代码如下:
'''
数据清洗---将日期和年级拆分(思路日期长度>年级,按长度判断)
'''
subname =lessondf.loc[:,'subName']
datelist=[]
gradelist=[]
for i in subname:
datestr=i.split(' ')
if len(datestr)==1:
datelist.append(datestr[0])
gradelist.append('暂无数据')
elif len(datestr[0])>len(datestr[2]):
datelist.append(datestr[0])
gradelist.append(datestr[2])
else:
datelist.append(datestr[2])
gradelist.append(datestr[0])
lessondf['date']=datelist
lessondf['Grade']=gradelist
#print(lessondf)
case3 --- 将日期列,继续拆分成开始日期和截止日期
'''
#数据清洗---将日期拆分(开始日期 和 结束日期 )
'''
date =lessondf.loc[:,'date']
from_datelist=[]
to_datelist=[]
for i in date:
datestr2=i.split('-')
#print(datestr2)
from_datelist.append(datestr2[0])
if len(datestr2)==1:
to_datelist.append('暂无数据')
else:
to_datelist.append(datestr2[1])
lessondf['from_date']=from_datelist
lessondf['to_date']=to_datelist
#print(lessondf)
case4 --- 数据清洗给channelid赋值
'''
#数据清洗---给channelid赋值
'''
for i in range(0,225):
date3 =lessondf.loc[i,'channelId']
if date3 ==1:
lessondf['channelId'][i]='语文'
elif date3 ==2:
lessondf['channelId'][i]='数学'
elif date3 ==3:
lessondf['channelId'][i]='英语'
elif date3 ==201:
lessondf['channelId'][i]='编程'
elif date3 ==4:
lessondf['channelId'][i]='物理'
elif date3 ==5:
lessondf['channelId'][i]='化学'
elif date3 ==6:
lessondf['channelId'][i]='生物'
elif date3 ==7:
lessondf['channelId'][i]='历史'
elif date3 ==8:
lessondf['channelId'][i]='地理'
elif date3 ==9:
lessondf['channelId'][i]='政治'
elif date3 ==14:
lessondf['channelId'][i]='道德与法制'
else :
pass
#print(lessondf.loc[:,'channelId'])
case5 --- 删除多余的列 ,“minprice” ,“maxprice”,“subname”,date
lessondf1=lessondf.drop(columns=['minPrice', 'maxPrice','date','subName','Grade'])
print(lessondf1.shape)
lesson表(一次清洗后)
3.2 二次数据清洗 ---excel
case1 重复课程均值处理
有一类课程是给整个学段开发,总报名人数重复出现了3次,将此类课程按出现次数取均值分别赋值到每个年级。
case2 --- 进增课程时长列(if函数,处理跨年异常值)
课程长度=结束日期-开始日期
当 结束时间-开始时间>0
时长= 结束时间-开始时间
当 结束时间-开始时间=0
时长=1
当 结束时间-开始时间<0
时长=12月31日-开始时间+(结束时间月份数-1)×30+结束时间日
case3 --- 个别异常值处理
二次清洗后结果
第四部分 : 数据提取
将teacher表和l清洗后的lesson表导入Navicat,方便用sql语句提取信息。
按照第一部分的脑图,将需要的信息拆解成问题的形式用SQL语句提取
(1) 一共有多少课程? (255)
(2) 三个学段各多少课程? (小学36 , 初中50 ,高中 139)
SELECT studyPhase,count(*) from sheet2
GROUP BY studyPhase
(3)每个年级各多少课程? (4 4 8 7 7 6 13 17 20 21 29 89 )
SELECT grade,count(*) from sheet2
GROUP BY grade
(4)每个年级下,各学科有多少课程?
SELECT grade,channelId,count(*) from sheet2
GROUP BY grade,channelId
(5)一共有多少学生报名? (323877)
SELECT sum(soldCount) from sheet2 ;
(6)每个学段各多少学生报名?
SELECT studyPhase,sum(soldCount) from sheet2
GROUP BY studyPhase ;
(7)每个年级下各学科多少学生报名?
SELECT grade,channelId,sum(soldCount) from sheet2
GROUP BY grade,channelId ;
(8)课程总收入?
SELECT sum(soldCount*price) from sheet2 ;
(9)三个学段课程收入?
SELECT studyPhase,sum(soldCount*price) from sheet2
GROUP BY studyPhase ;
(10)每个年级下各学科多少卖了多少钱?
SELECT grade,channelId,sum(soldCount*price) from sheet2
GROUP BY grade,channelId ;
(11)一共有多少名辅导老师?
SELECT count(DISTINCT nickname) from teacher ;
(12)每个年级下对应的学科各有多少老师?
SELECT grade,channelId,count(DISTINCT t.id ) from sheet2 as s , teacher as t
where s.id=t.lessonid
GROUP BY grade , channelId ;
(13)老师代课数量排名?
SELECT nickname,id,count(lessonid)from teacher as t
GROUP BY id
ORDER BY count(lessonid) desc
(14)老师代课学生数排名
SELECT nickname,t.id, count(DISTINCT lessonid) ,SUM(DISTINCT s.soldCount) from teacher as t ,sheet2 as s
where s.id= t.lessonid
GROUP BY t.id
ORDER BY SUM(DISTINCT s.soldCount) desc;
(15)老师营收排名?
SELECT nickname,t.id, count(DISTINCT lessonid) ,SUM(DISTINCT s.soldCount*price) as s from teacher as t ,sheet2 as s
where s.id= t.lessonid
GROUP BY t.id
ORDER BY s desc;
将查询结果导出,从以下4个维度制作图标进行描述性分析
第五部分 : 数据数据可视化
数据提取部分已经获得了我们需要的数据,数据可视化的过程就是选择恰当的图标来表达要描述的内容。
笔者这次分析主要是展示“分布”,“构成”,“联系”
因此选择: 柱状图,累计柱状图,散点图 ,为主要的说明方式。
第六部分 : 撰写报告
报告分为以下几个模块展开,笔者输出报告后会另写一篇文章分享报告内容
(1)背景与目的
(2)描述性分析
(3)相关性分析
(4)结论
本文主要是分享一个数据分析的全过程,最终的报告结果笔者会在另一篇文章中分享。
python猿辅导_如何用数据分析方法剖析“猿辅导”K12课程相关推荐
- python轮胎_如何用数据分析方法剖析途虎轮胎数据
前言 本次分析只是用途虎养车网案例分享数据学习方法和方法论,禁止用作商业目的,同时声明数据与关键指标未必真实有效. 概述 笔者将通过以下环节,展示整个过程. 涉及知识: 结构化思维,描述性分析,探索性 ...
- python电商_电商数据分析(python)
一.背景及目的 从多维度对某平台2016年电商数据进行分析,总结销售规律,为来年销售计划做准备,指导之后的产品销售. 二.理解数据 三.提出分析思路 四.数据清洗 此部分请见我之前写的文章:电商数据分 ...
- python写数学公式_如何用Markdown写论文?
本文用简明的样例,介绍如何使用Markdown和自动化工具帮你处理数学公式.参考文献引用.图片交叉索引等学术论文写作中常见的棘手问题.快来试试吧. (由于微信公众号外部链接的限制,文中的部分链接可能无 ...
- python地图标点_如何用python画地图上的标注线?
我们平时看文章的时候会遇到一些不太好理解的地方,如果上面有标注那就事半功倍了.当然在地图中也是如此.之前我们学会了很多画图的技巧,但是忽略了标注这种细节的重要作用.小编经过一番学习和整理,清楚了这部分 ...
- 怎么用python分析数据_如何用python进行数据分析?
.Python数据分析流程及学习路径 数据分析的流程概括起来主要是:读写.处理计算.分析建模和可视化四个部分.在不同的步骤中会用到不同的Python工具.每一步的主题也包含众多内容. 根据每个部分需要 ...
- python写透视挂_如何用Python openCV 用透视变换的方法对图像进行矫正
.需要矫正的图片1 需要矫正的图 矫正后的结果: 矫正后的图 需要矫正的图片2 矫正前 矫正后 # import the necessary packages from imutils.perspec ...
- python 编程效率_如何有效提升数据分析效率?五大Python技巧
如何有效提升数据分析效率?相信这是所有数据分析工作者都想解决的问题.本文整理了五大python技巧,分别是Pandas Profiling:使用 Cufflinks 和 Plotly 绘制 Panda ...
- python预测房价走势_如何用 Python 预测房价走势?
原标题:如何用 Python 预测房价走势? 买房应该是大多数都会要面临的一个选择,当前经济和政策背景下,未来房价会涨还是跌?这是很多人都关心的一个话题.今天分享的这篇文章,以波士顿的房地产市场为例, ...
- python贪吃蛇_如何用Python写一个贪吃蛇?
阅读文本大概需要 5 分钟 作者:Hawstein http://hawstein.com/2013/04/15/snake-ai/ 前言 这两天在网上看到一张让人涨姿势的图片,图片中展示的是贪吃蛇游 ...
最新文章
- vsftpd的主配置文件是什么linux,linux下vsftpd配置文件选项详细说明
- vuex之state-状态对象的获取方法(三)
- javascript(arguments)
- C语言程序设计0004,C语言程序设计0004.doc
- ios 检测是否联网_秋招|阿里 iOS 五轮面经分享,已收到阿里的意向书
- iOS核心动画之CoreAnimation
- P2634 [国家集训队]聪聪可可
- angular8实现对象数组根据某个属性排序(多个也可以)
- Android Canvas的drawText()和文字居中方案
- 无法从“cstring”转换为“lpcstr”_U盘重装系统后,无法使用?
- Spring(1)-IOC
- VSS (Visual Source Safe 2005) 用法详解(转载)
- 中国移动锁定数据业务新战略
- 经验总结21--抓取WEB数据,汇率,HtmlAgilityPack
- 微博市值破百亿,真的只是恰巧赶上奥运了吗?
- uKey双向认证https
- 数据库实验四:数据高级查询
- 基于SpringBoot+微信小程序的壁纸小程序
- 在虚拟机上安装gho、esd(wim)系统镜像文件
- webp学习http://isux.tencent.com/introduction-of-webp.html