数据解读独角兽企业“猿辅导”(第二部分)

上一次的内容中,我们已经把确定目标数据获取的部分完成了,接下来我们来讲一下如何进行数据处理数据展示吧。

第三部分:数据处理

数据处理是数据分析的核心部分,我也给它打了50%的权重。之前的数据获取部分,我们拿到了1615条原始的课程数据。但是,这个数据中可能有无法使用和重复等情况,而且我们还要根据之后展示数据的要求进行数据提取。可见,我们的数据处理又可以分成两步:数据清洗和数据提取

一、数据清洗

我们还是使用python来对数据进行清洗。在之前的数据获取中我们拿到了三张表:总课程表、课程详情表和教师表

我们先来看一下总课程表:

可以看出,我们之前为了爬取课程详情在课程表中增加了lessonurl列,在清洗时可以去掉。同时根据年级(grade)我们还可以增加一列学段(小学、初中、高中),可以为之后的展示提供更多的角度。

代码如下

#导入模块
import numpy as np
import pandas as pd

#打印出前5行,以确保数据运行正常
lessonDf.head()

#选择子集
lessonDf = lessonDf[['grade','channelid','lessonid','lessonname']]

#通过条件判断筛选
#构建查询条件
querySer = lessonDf['lessonid'] != 'groups/'
#根据查询条件筛选
lessonDf = lessonDf.loc[querySer, : ]
lessonDf.shape

#通过条件判断筛选
#构建查询条件
querySer = lessonDf['lessonid'] != 'groups/'
#根据查询条件筛选
lessonDf = lessonDf.loc[querySer, : ]
lessonDf.shape

#给channelid赋值
for i in range(0, 1389):
    channel = lessonDf.iloc[i,1]
    if channel == 1:
        lessonDf.iloc[i,1]='语文'
    elif channel == 2:
        lessonDf.iloc[i,1]='数学'
    elif channel == 3:
        lessonDf.iloc[i,1]='英语'
    elif channel == 201:
        lessonDf.iloc[i,1]='编程'
    elif channel == 4:
        lessonDf.iloc[i,1]='物理'
    elif channel == 5:
        lessonDf.iloc[i,1]='化学'
    elif channel == 6:
        lessonDf.iloc[i,1]='生物'
    elif channel == 7:
        lessonDf.iloc[i,1]='历史'
    elif channel == 8:
        lessonDf.iloc[i,1]='地理'
    elif channel == 9:
        lessonDf.iloc[i,1]='政治'
    elif channel == 14:
        lessonDf.iloc[i,1]='道德与法制'
    else :
        pass

#创建studyphase列
lessonDf['studyphase'] = lessonDf['grade']

#给studyphase赋值
for i in range(0, 1389):
    phase = lessonDf.iloc[i,4]
    if 0< phase<=6:
        lessonDf.iloc[i,4]='小学'
    elif 6< phase <=9:
        lessonDf.iloc[i,4]='初中'
    elif phase > 9:
        lessonDf.iloc[i,4]='高中'
    else :
        pass

#去重
lessonDf = lessonDf.drop_duplicates()

#导出数据
lessonDf.to_excel('lesson.xls')

清洗结果如下:


同样的,我们也对课程详细表和教师表进行去除脏数据、去重等操作,导出teacher和lessondetail两张表:

二、数据提取

处理好数据之后,下一步就是根据实际的数据展示需求来提取数据了。参考下面的脑图我们可以更好的理解应当提取哪些数据:

这幅脑图和第一部分爬取数据时的脑图相比更加清晰,每个子主题都可以对应一个提数需求。这里我将上面数据清洗得到的三张表导入Sequel Pro,使用SQL语句来提取所需的数据。

1、学科、学段、年级下课程数排名

(1)不同学科的课程数量
select channelid '学科类型', count(distinct lessonid) '课程数量' from lesson
group by channelid;

(2)不同学段的课程数量
select studyphase '学段', count(distinct lessonid) '课程数量' from lesson
group by studyphase;

(3)不同年级的课程数量
select grade '年级', count(distinct lessonid) '课程数量' from lesson
group by grade;

2、学科、学段、年级下课程报名人数排名

(1)不同年级、学科下报名人数
select grade '年级', channelid '学科', sum(signup_number) '报名人数' from lessondetail d
left join
(select distinct grade, channelid, lessonid
from lesson) t
on d.lesson_id = t.lessonid
group by grade, channelid

(2)不同学段下报名人数
select studyphase '学段', sum(signup_number) '报名人数' from lessondetail d
left join
(select distinct studyphase, lessonid
from lesson) t
on d.lesson_id = t.lessonid
group by studyphase

(3)不同年级下课程报名人数
select grade '年级', sum(signup_number) '报名人数' from lessondetail d
left join
(select distinct grade, lessonid from lesson) t
on d.lesson_id = t.lessonid
group by grade

3、学科、学段、年级下老师数量排名

老师总数量
select count(distinct teacher_id) from teacher;

(1)不同学科的老师数量
select channelid '学科', count(teacher_id) '教师数'
from (select distinct channelid, teacher_id
from lesson l
join teacher t
on l.lessonid = t.lesson_id) t
group by channelid

(2)不同学段的老师数量
select studyphase '学段', count(teacher_id) '教师数'
from (select distinct studyphase, teacher_id
from lesson l
join teacher t
on l.lessonid = t.lesson_id) t
group by studyphase

(3)不同年级的老师数量
select grade '年级' , count(teacher_id) '教师数'
from (select distinct grade, teacher_id
from lesson l
join teacher t
on l.lessonid = t.lesson_id) t
group by grade

(4)课程配师的分布情况
select teacher_num '课程配备教师个数', count(t.lesson_id) '课程数量' from(
select lesson_id, count(1) as teacher_num from teacher
group by lesson_id) t
group by teacher_num

(5)老师上的课程数分布
select teacher_id, ct '上课数' from(
select teacher_id , count(1) ct from teacher
group by teacher_id) t
order by t.ct desc

4、学科、学段、年级下营收情况排名

(1)不同学科的营收
select channelid '学科' , sum(profit) '营收' from
(#对学科下的课程id去重
select channelid, lesson_id, count(lesson_id), price*signup_number profit
from lessondetail d
join lesson l
on d.lesson_id = l.lessonid
group by channelid, lesson_id) t
group by channelid

(2)不同学段的营收
select studyphase '学段' , sum(profit) '营收' from
(#对学段下的课程id去重
select studyphase, lesson_id, count(lesson_id), price*signup_number profit
from lessondetail d
join lesson l
on d.lesson_id = l.lessonid
group by studyphase, lesson_id) t
group by studyphase

(3)不同年级+学科的营收
select grade '年级' ,channelid '学科', sum(profit) '营收' from
(#对年级下的课程id去重
select grade, lesson_id, channelid, count(lesson_id), price*signup_number profit
from lessondetail d
join lesson l
on d.lesson_id = l.lessonid
group by grade, lesson_id, channelid) t
group by grade, channelid

(4)老师对营收的贡献排名
select teacher_id '教师id' , studyphase '学段' , channelid '学科' , sum(signup_num) '学生数',
count(1) '代课数' , sum(profit) '营收' from
(select lesson_id, signup_num, profit from
(#对多老师的课程营收分配成相应价格
select l.lesson_id, count(l.lesson_id), sum(signup_number)/count(l.lesson_id) signup_num,
price*signup_number/count(l.lesson_id) profit
from lessondetail l
join teacher t
on l.lesson_id = t.lesson_id
group by l.lesson_id) t1) t2
join teacher t
join lesson l
on t.lesson_id = t2.lesson_id
and t2.lesson_id = l.lessonid
group by teacher_id, studyphase, channelid

(5)课程对营收的贡献排名
select lesson_id, sum(price*signup_number) profit
from lessondetail
group by lesson_id


以上SQL语句基本上满足了大部分的提数需求。此外,还有一张表可以用来计算相关性矩阵:

合并表

select d.lesson_id, price, signup_number,
studyphase, grade, channelid,
price*signup_number profit
from lessondetail d
join lesson l
on d.lesson_id = l.lessonid

第四部分、数据展示

经过以上步骤的数据提取,我们可以根据需求来展示数据了。一个比较经典的图是这样的:

考虑到我们需要展示的数据主要目的为比较和构成,因此我选择条形图、柱状体、饼图等基本图形来进行展示。

由于篇幅有限,这里只展示一下相关性矩阵:

可见,课程的营收情况主要和报名人数以及年级成正相关。其他具体数据展示我会通过一个具体的报告进行呈现,敬请期待。

小结

本篇文章主要讨论了对猿辅导网站获取的数据进行清洗和提数的过程。在清洗数据时利用python简化流程,在提数过程中先使用Xmind确定提数需求,再使用SQL语句完成提数。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,496评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,407评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,632评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,180评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,198评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,165评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,052评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,910评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,324评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,542评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,711评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,424评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,017评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,668评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,823评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,722评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,611评论 2 353

推荐阅读更多精彩内容