数据分析/歌者的粉丝都是什么模样

去社区提问

简介:网站成千上万看似简单的评论其实暗藏玄机,利用它们可以分析偶像的粉丝们都有怎样的特点,用户活跃时段等。从第一个案例打开Python数据分析的大门吧。

歌者的粉丝都是什么模样

你也被刷屏了吗?

献给毕业季的歌

五四前夕,bilibili推出的演讲视频《后浪》,让‘小破站’火速出圈,在朋友圈掀起一阵转发热潮。

520当天, B站又‘搞事情’~联合毛不易发布一首《入海》,“告白”了所有即将毕业的“小大人”们。

歌曲MV以主人公毕业为原点,追忆过去,展现了普通人毕业后现实的社会生活。

被分手,面试未通过,好友离别……

有别于《后浪》被人诟病的“毒鸡汤”式内容,毛不易的这首歌中展现了更为真实的’后浪们‘。

毕竟走出象牙塔,不是所有人都是体面的,虽然知道前方充满艰难,但仍愿坚持‘带着倔强不投降’,或许这才是真正勇敢的’后浪们’吧~

这首歌一经发布就在B站引爆了话题点,在B站播放量达到了800万+,收获了5.2万弹幕,最高全站日排行第1名。

毛不易的这首《入海》究竟吸引了哪些观众?大家的对作品的评论又是如何?今天让我们一起用Python数据分析来看看结论。

特别提示:如果暂时不理解代码的含义也没有关系~只通过这些案例了解Python用途就达到了目标。11课程后将进入详细的Python语法学习,要继续加油呀。

预告一下

在这里为你倾情献上了B站上这首歌MV的评论数据,请过目~

数据共计19099条,包括了八个字段:

  • 用户名
  • 用户性别
  • 用户标签
  • 用户账号等级
  • 评论内容
  • 使用设备
  • 评论时间
  • 点赞数

接下来我将带领你玩转数据,做些有趣的分析:

  1. 观众性别比例分析
  2. 用户客户端分布
  3. 评论用户等级分布
  4. 评论时间走势

看过MV后有同学在评论中说:毕业之后再也不能逃课了,逃不掉的工作让我遭受社会毒打。

但我想说,如果能重来一次,我一定好好珍惜课堂,一节课都不逃!让有用的知识点一点点累积(手动狗头)。

每天问自己一遍,今天的我比昨天更博学了吗?

好了,今天的博学之路就从现在开启,跟我一起学习第一个数据分析实操案例吧~

每位同学的基础不同,对很多同学来说,课程中的代码还不能完全理解,也完全不用担心,这并不影响你后续的学习,重要的是掌握思路和方法。

关于Python语法和具体代码的研究可以一步步来学习~

读读数据

第一步,使用import导入需要使用的模块。Python有着丰富多彩的第三方模块。

可以想象这里有一个巨大的夹娃娃机器,每个娃娃都代表一个Python模块。不同娃娃口袋中又有各自的道具,命中率偷偷设定为100%。

import就好比娃娃机的夹子,百发百中地为我们获取想要的娃娃,借助它们口袋中的道具直接快速地实现我们的小心愿。下面导入分析过程要使用的所有模块:

  1. # 导入包
  2. import numpy as np
  3. import pandas as pd
  4. import matplotlib.pyplot as plt
  5. import time
  6. from collections import Counter
  7. from pyecharts.charts import Bar, Pie, Line, WordCloud, Page
  8. from pyecharts import options as opts
  9. from pyecharts.globals import SymbolType

帮助我们走捷径的道具buff就位,下面这节课的重点都要围绕数据展开,理所应当先查看一下数据啦。那Python语言如何给计算机下指令,让它展示数据给我们呢?

看下面两行代码:

代码练习:

编程区

  1. # 读入数据
  2. df = pd.read_excel('B站评论数据-入海5.23.xlsx')
  3. df.head()

终端区

这里的read_excel()和head()都是前面导入pandas这个娃娃口袋中的道具,使用read_excel()方法可以读取存在excel文件里的数据,head()方法帮我们展示出数据的前五行内容。

这个文件共有多少条数据呢,到这里也许你能猜到了,依然可以直接运用现成的方法(不得不感叹,这娃娃夹的真值)。

代码练习:

编程区

  1. df.shape

终端区

看,一行代码得出,数据的形状是19099行,8列。

Python的代码是不是非常易懂,即使之前没有编程基础,通过代码也可以大概猜测出它们所实现的功能是什么。

恭喜你成功迈出第一步,读取到了数据,那么问题来了,这些数据可以直接拿来使用吗?

让数据变漂亮

现有的数据,可能存在一些错误,比如大量重复值,直接影响后续结果准确性;也可能数据格式不是我们想要的样子。

因此在开始分析数据之前,需要让数据变得更加‘漂亮’,更符合我们的需求。在这里要解决下面的几个问题:

  1. 重复值处理
  2. 时间戳数据处理

看了上面的两点要处理的内容,此刻你应该是一头雾水,别忘了,你的博学之路上还有我这个领路人呢(还是不离不弃那种类型的)~

快上车~带你一起给数据变个身。

先来解决重复值问题,使用drop_duplicates方法删除数据中的重复值,看下面的代码:

代码练习:

编程区

  1. # 重复值
  2. df = df.drop_duplicates()
  3. df.shape

终端区

df.shape可以查看删除重复后的数据量,依然是19099行,说明原数据中没有完全相同的数据出现。

使用info()这个方法查看数据摘要,包括所有列的列表,非空值的数量以及数据类型:

代码练习:

编程区

  1. df.info()

终端区

结果中的Non-Null表示对应列有多少条非空数据;Dtype表示数据的类型。例如‘等级’一列共有19099条非空值,数据类型为int也就是整型。

之前展示数据的时候不知道你有没有发现,‘评论时间’一栏看起来有些奇怪,来回忆一下:

我们常见的时间表示方法不应该是时:分:秒这种格式吗?这看起来怎么只是一串数字呀,难道…是数据出问题了?

抬起头看黑板~新奇的知识点又要增加了,这里为你介绍一种全新的时间表达方式:时间戳

时间戳是指格林威治时间1970年01月01日00时00分00秒起至当下的总秒数。

来百度一下,是这样说的:

到这里你一定会有疑问,直接使用常用的表示方法不就好了,为什么要用时间戳,看起来非常不直观。

其实不同数据库对时间类型有不同解释,为了实现跨平台性,时间戳是一个很好的方法。

另一方面,用户的桌面时间非常容易改变,这种方法也能有效避免这个问题。

接下来把时间戳转换为我们常用的表示形式:

代码练习:

编程区

  1. df['评论时间'] = pd.to_datetime(df['评论时间'], unit='s')
  2. df['评论时间'] = df['评论时间'].dt.tz_localize('utc').dt.tz_convert('Asia/Shanghai').dt.strftime('%Y-%m-%d %H:%M:%S').astype(str)
  3. df.head()

终端区

数据终于成为了我们想要的模样,撒花庆祝。

铺垫准备都做好,下面就要火速进入主题了,请博学之路上的同学们坐稳扶好~

酷炫的可视化效果

Python的强大之处不仅在于它能快速处理大批量数据,还能把结果用直观的可视化图表展示出来。折线图,饼图,散点图,雷达图,柱状图应有尽有,各种动态效果图也都能轻松实现。

有一天老板交给你一份数据,你三下五除二就处理好了,做了一份报告,把各种酷炫的图表摆在他面前,头头是道地分析你通过数据得出的结论,以及对未来业务的建议。结束时,会议室响起了雷鸣般的掌声,老板向你投来赞许的目光,办公室其他小姐姐看向你的眼神中都带有些许崇拜。

工资方面…或许马上要走上脱贫致富的道路了!

这是不是你的内心os,这下升职加薪指日可待~

咳咳不说那么多,仰望完星空,该脚踏实地了,先学好这节课呀各位同学们,想要了解更多加薪技能可以添加班主任微信,偷偷告诉你,早就为你准备好了丰厚的大礼包哦。

课程一开始使用import导入的pyecharts和matplotlib模块,都可以实现数据可视化,提供了各种现成的方法供我们使用。

首先来看看《入海》这首歌曲MV观众中,男女性别占比,毛毛老师究竟更吸引男粉丝还是女粉丝呢?

评论性别占比

用户注册时,性别可选‘男’,‘女’或‘保密’,在统计时,忽略选择‘保密’的用户,不计入结果。

很简单,只需要操作‘用户性别’这一列的内容,把三个内容对应的数量统计出来,再把‘保密’一栏的数据删除不做统计就可以啦。

用下面几行代码实现上述统计功能:

代码练习:

编程区

  1. # 总体评分分布
  2. sex_num = df['性别'].value_counts()
  3. sex_num.drop('保密', inplace=True)
  4. print(sex_num)

终端区

使用value_counts方法统计‘性别’一列的不同数据总和,再使用drop方法把‘保密’一栏删除,最后打印得到结果。

由上面的数据可以得到,男性观众4537人,女性观众3759人。是不是有点出乎意料,男性数量略高与女性观众。

用下面的代码绘制饼图来展示结果:

代码练习:

编程区

  1. # 绘制饼图
  2. data_pair = [list(z) for z in zip(sex_num.index.tolist(), sex_num.values.tolist())]
  3. # 绘制饼图
  4. pie1 = Pie(init_opts=opts.InitOpts(width='1350px', height='750px'))
  5. pie1.add('', data_pair, radius=['35%', '60%'])
  6. pie1.set_global_opts(title_opts=opts.TitleOpts(title='评论用户性别占比'),
  7. legend_opts=opts.LegendOpts(orient='vertical', pos_top='15%', pos_left='2%'))
  8. pie1.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}:{d}%"))
  9. pie1.set_colors(['#EF9050', '#3B7BA9', '#6FB27C'])
  10. pie1.render()

终端区

从图中可以看出:男性用户占比54.69%,女性用户占比45.31%,看来B站上毛不易的男粉丝数量还挺庞大~

客户端分布

观看《入海》视频的用户都使用的是什么移动设备呢?和统计用户性别占比相同,这次我们需要操作的是‘设备’这一列的数据。

分别统计:苹果用户phone,安卓用户android,平板用户pad,未知设备unknown四项内容的数量就可以得到结果。同样使用value_counts方法实现:

代码练习:

编程区

  1. device_num = df.设备.value_counts(ascending=True)
  2. device_num

终端区

绘制一个柱状图来展示一下:

代码练习:

编程区

  1. # 柱形图
  2. bar1 = Bar(init_opts=opts.InitOpts(width='1350px', height='750px'))
  3. bar1.add_xaxis(device_num.index.tolist())
  4. bar1.add_yaxis('', device_num.values.tolist(),
  5. label_opts=opts.LabelOpts(position='right'))
  6. bar1.set_global_opts(title_opts=opts.TitleOpts(title='评论客户端分布'),
  7. visualmap_opts=opts.VisualMapOpts(max_=3000))
  8. bar1.reversal_axis()
  9. bar1.render()

终端区

经过分析发现,iphone的用户占了很大的比例,远超安卓系统的用户,平板用户排名第三。

用户等级分布

不光转正成为会员要接受残酷的答题考验,B站根据用户的参与程度还给用户划分了Lv0-Lv6几个等级,数字越大,等级越高。不得不说小破站真的很严格。

同样的方法,我们统计一下观看《入海》视频的用户等级分布:

代码练习:

编程区

  1. level_num = df.等级.value_counts()
  2. level_num

终端区

画一个饼图呈现结果:

代码练习:

编程区

  1. data_pair2 = [list(z) for z in zip(['LV' + i for i in level_num.index.astype('str').tolist()] , level_num.values.tolist())]
  2. # 绘制饼图
  3. pie2 = Pie(init_opts=opts.InitOpts(width='1350px', height='750px'))
  4. pie2.add('', data_pair=data_pair2, radius=['35%', '60%'])
  5. pie2.set_global_opts(title_opts=opts.TitleOpts(title='评论用户等级分布'),
  6. legend_opts=opts.LegendOpts(orient='vertical', pos_top='15%', pos_left='2%'))
  7. pie2.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}:{c}({d}%)"))
  8. pie2.set_colors(['#EF9050', '#3B7BA9', '#6FB27C', '#FFAF34'])
  9. pie2.render()

终端区

在《入海》这首歌的评论用户上,评论中5级的占比最高为36.1%,接着是4级占比26.31%,6级占比最低仅为3.24%,毕竟要成为六级大佬实在太难了。

评论时间走势图-小时

这首歌的MV是5月20日在B站发布的,那么从发布到成功登上热搜,这期间哪个时段用户的评论量最大,引起的话题最多呢?

下面我们一起来看看评论量走势和时间的关系。

统计的数据都产生在2020年,年份这个时间标识可以忽略,只观察日期和小时带来的影响。我们额外添加一条时间的字段,然后再查看一下前几行数据:

代码练习:

编程区

  1. df['时间'] = df.评论时间.str.split('-').str[1] + '-' + df.评论时间.str.split('-').str[2]
  2. df.head()

终端区

最后一列成功出现了新加入的数据字段。

现在时间是以5-20 12:07:45这样类似的模式存放,我们要统计各小时评论数量,第一个冒号后的分钟和秒数都可以忽略不考虑。

下面用冒号:分割‘时间’这栏的数据就能得到我们需要的日期和小时的数据。

代码练习:

编程区

  1. df['时间'] = df.时间.str.split(':').str[0]
  2. time_num = df.时间.value_counts().sort_index()
  3. time_num[:5]

终端区

下面又来到了精彩的作图时间,选用面积图来表示时间和评论数量之间的关系:

用下面两行代码设定横坐标为时间,纵坐标表示评论数量。

  1. # 产生数据
  2. x1_line1 = time_num.index.values.astype('str').tolist()
  3. y1_line1 = time_num.values.tolist()

来看一下最终效果。

代码练习:

编程区

  1. # 绘制面积图
  2. line1 = Line(init_opts=opts.InitOpts(width='1350px', height='750px'))
  3. line1.add_xaxis(x1_line1)
  4. line1.add_yaxis('', y1_line1, areastyle_opts=opts.AreaStyleOpts(opacity=0.3),
  5. markpoint_opts=opts.MarkPointOpts(data=[
  6. opts.MarkPointItem(type_='max', name='最大值')
  7. ]))
  8. line1.set_global_opts(title_opts=opts.TitleOpts('各个时段评论人数'),
  9. xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate='30'))
  10. )
  11. line1.set_series_opts(label_opts=opts.LabelOpts(is_show=False),
  12. axisline_opts=opts.AxisLineOpts()
  13. )
  14. line1.render()

终端区

从5月20日8:30发布MV后,评论数量逐渐上升,12点左右有一个快速增加,达到高峰。后续随着时间的推移,评论人数逐渐减少,趋于平缓。

恭喜你成功和我一起完成了第一个数据分析的案例学习~现在可以承认‘今天的我比昨天更博学了一点’了。

在这节课中,我们学习了读取数据->数据预处理->可视化展示的数据分析流程。

利用数据对B站《入海》视频的观看用户做了分析,剖析了毛老师的粉丝群体性别分布,客户端使用情况,用户等级分布,评论时间走势情况。

看到这里可能你对Python的应用有了一些基本的认知,其实它比你想象的还要更加强大,可以实现的功能还有很多很多,是个妥妥的‘宝藏编程语言’,等待你来挖掘~

想要继续深入研究更多内容,欢迎扫描下方二维码添加班主任微信,和更多同学一起交流学习,我们下节课不见不散哦。

扫描下方二维码,添加班主任微信

已经添加过班主任的同学,可以直接联系对应老师,无需重复添加哦。

数据分析 1/3

歌者的粉丝都是什么模样

1.0x

恭喜完成本课时的学习!
坚持学习

行动力超过

累计学习

学习下一课时