python熊猫弹幕_Pandas+Matplotlib:视频弹幕统计分析

本文通过Python的Pandas和Matplotlib库分析B站爬取的弹幕数据,研究弹幕量与视频高曝光时段及自然时间的关系。首先,统计Excel文件中每秒弹幕数量,发现数据量过大,处理后进行每秒弹幕统计,并优化统计方法。接着,以5秒为间隔进行柱状图可视化,揭示弹幕分布特点。此外,还展示了如何处理Excel文件的多个表单,以天为单位统计弹幕量并进行可视化,分析热点事件随时间的变化趋势。
摘要由CSDN通过智能技术生成

弹幕[dàn mù] (danmaku),中文流行词语,指的是在网络上观看视频时弹出的评论性字幕。源自日本弹幕视频分享网站(niconico动画),国内首先引进为Acfun以及后来的哔哩哔哩网站。

大量吐槽评论从屏幕飘过时效果看上去像是飞行射击游戏里的弹幕,所以NICO网民将这种有大量的吐槽评论出现时的效果做弹幕。

在中国,本来只有大量评论同时出现才能叫弹幕,但是随着误用单条评论也能叫弹幕了。

想法:弹幕量与视频中的高曝光片段出现时间段是否有关?弹幕量与自然时间之间是否有一定关联性?

数据:从哔哩哔哩网站上爬下来的弹幕数据

分析过程:爬下来的Excel数据文件,里面是啥样的?数据是否完整?如何通过视频时间和自然时间分别统计弹幕量?如何以可视化的形式表达?

上述就是整个分析流程,下面开始一步步进行

任务一:对于 '热点事件.xlsx' 文件的Sheet3表单而言,需要统计视频时间中每秒内弹幕的数量并可视化展示

import pandas as pd

import matplotlib.pyplot as plt

①读入数据

fpath = './datas/热点事件.xlsx'

df = pd.read_excel(fpath,sheet_name='Sheet3')

这里,我已知分析所用数据在Sheet3表单中,所以直接调用了。

其实在不知情的情况下,应该先对Excel文件进行“结构性”读取(自己理解的)。

如何“结构性”读取,在后面会用到。

②查看数据的“样子”

df.head()

一看,有用的就前两列,第一列是弹幕发送的视频时间,第二列是数量。

df.shape # 结果为(1048575, 6)

好大的数据量啊,有问题!EXCEL表格文件最多就只有1048575行。

df.dropna(axis="index", how='all', inplace=True)

先删除全部为空值的行试试。

df.shape # 结果为(501, 6)

这里一看,好家伙,全是空值.....还好进行了空值处理。最终需要处理的总共501行数据。

其实这里回头想,少了一步,我们看了开头的五行数据,其实也可以看看结尾的五行数据是啥样子的。

后面重新做的时候我发现,在原始表格第1048575行的数据是统计了有多少行数据= =|||,这里应该是人为操作失误。

③按照视频时间的每秒进行弹幕量统计

df.loc[(0 <= df['时间']) & (df['时间'] < 1),'数量'].sum() # 运行结果为8.0

由于"时间"列中均是精确到秒后三位小数,这里利用df.loc进行区域限定,然后借助"数量"列进行求和。

这样就统计出了0至1秒,也就是1秒内的弹幕量,如法炮制,求出每秒的弹幕量。

# 基于上述方法,写一个for循环,解决战斗

for i in range(501):

count = df.loc[(i <= df['时间']) & (df['时间'] < i+1),'数量'].sum()

print('第{}秒内共有{}条弹幕'.format(i, count))

运行结果如下图所示。

通过上述代码运行结果会发现,在109秒后出现的都是0条弹幕。

为啥是这样?因为虽然是501条,但是要计算每1秒内的弹幕量,这样累加之后,总行数就远远低于501行了。

这样看来,欠考虑。应该基于最后一条弹幕的秒数,给range()里面的参数赋值。

# 按照前面所想,可以看出以秒为单位的时间段最终为109.420秒

# 因此,给range()赋值110即可,为啥不是109?因为range()里面是左闭右开区间,取110意味着[0,110)

for i in range(110):

count = df.loc[(i <= df['时间']) & (df['时间'] < i+1),'数量'].sum()

print('第{}秒内共有{}条弹幕'.format(i, count))

为啥做上述的优化?

其实是我做到可视化部分发现的问题,回过头来在这里优化了。

④可视化展示

# 最后用柱状图可视化展示

# 这里要注意plt.bar()函数默认颜色循环使用,如果这里不指定一个颜色,柱状图会变得五颜六色

for i in range(110):

count = df.loc[(i <= df['时间']) & (df['时间'] < i+1),'数量'].sum()

#print('第{}秒内共有{}条弹幕'.format(i, count))

plt.bar(i, count, color='#008B8B')

plt.show() # 这里相当于在一块画布上每次画一条柱状图,直到for循环结束,输出结果

看看每5秒统计一次的结果。

plt.rcParams['font.sans-serif'] = ['SimHei']

plt.rcParams['axes.unicode_minus'] = False

# 最后,以5秒为一个间隔,看看弹幕的分布情况(有时候精细未必是好事,扩大间隔有助于分析问题)

for i in range(0, 110, 5):

count = df.loc[(i <= df['时间']) & (df['时间'] < i+5),'数量'].sum()

plt.bar(i, count, width=1, color='#008B8B') # 给定个宽度,出图看的紧凑些

plt.xlabel('弹幕时间(秒)', fontsize=12)

plt.ylabel('弹幕量(条)', fontsize=12)

plt.savefig('fix11.svg', dpi=500) # 保存

plt.show() # 这里相当于在一块画布上每次画一条柱状图,直到for循环结束,输出结果

从上图上就能很明显看出:

在视频时间10至25秒、65至75秒、90至95秒以及最后时刻,弹幕量较为集中。

再次观看视频发现,这些弹幕集中的某些视频时间段刚好对应视频中的高潮片段,符合观众观看行为。

任务二:对于 '热点事件.xlsx' 文件的原数据表单而言,需要统计以自然时间每天的弹幕数量并可视化展示

这里,假设我们不清楚拿到的Excel文件内部啥样子,你可以这样打开观察。

先看看文件中有多少个sheet(表单)。

但是按照以往读取Excel文件,你会发现,只能读取到第一个表单的数据(默认的)。

import pandas as pd

import matplotlib.pyplot as plt

file_path = './datas/热点事件.xlsx'

xx = pd.read_excel(file_path)

有同学说,你可以加上表单名称参数啊。但是刚说过了,我们假设拿到的数据,你完全不知道里面啥样。怎么办?

这时候可以用另一种Excel文件读取方式:pd.ExcelFile( )

data = pd.ExcelFile(file_path)

data.sheet_names

这样就可以将读取Excel数据的所有表单名称打印出来了,如下图。

假设我需要的数据在表单名为‘原数据’中,则通过如下代码:

df = data.parse('Sheet5')

这样就回到了我们之前的DataFrame的操作流程上来了。

如上图所示,又出现了新问题。读取时,原文件开始有空行,所以造成读取后,原本的列标签变成了数据。这里只需要设定指定一行为索引即可,代码如下:

df = data.parse('Sheet5', header=1)

完美解决,开始数据分析。

①首先将第一列(日期)作为标签列

df = df.set_index('行标签') # 将“行标签”设置为index

这时又发现,其中columns的值为‘以下项目的计数:数量’,太绕口,写起来太麻烦。

利用rename( )修改列名,以字典的形式传入值,进行修改,代码如下:

df_clearn = df.rename(columns={'以下项目的计数:数量':'counts'})

②以天为单位进行统计

df_clearn.resample('d').sum()['counts']

如果只统计2018年全年的,可以使用如下代码:

df_day = df_clearn.resample('d').sum()['counts']

df_2018 = df_day['2018']

③可视化展示

plt.rcParams['font.sans-serif'] = ['SimHei']

plt.rcParams['axes.unicode_minus'] = False

plt.figure(figsize=(10,4))

plt.plot(df_2018.index, df_2018, color='#008B8B')

plt.xlabel('自然时间(天)',fontsize=12)

plt.ylabel('弹幕量(条)',fontsize=12)

plt.savefig('picture.svg', dpi=500)

plt.show()

从上图上就能很明显看出:

随着自然时间的推移,热点事件的评论热度会慢慢降低直至“冷却”,符合常理。

今天的分享到这里就结束了,我最近收获最大的就是拿到一个简单的实际问题,通过自己所学,查漏补缺,这样进步会很快,我还是不建议类似于A到Z的背单词方法,其实背作文何尝不是一种背单词的方法呢?

哈哈,隐喻,自行理解~

END

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值