pyecharts可视化B站弹幕

简介: pyecharts可视化B站弹幕

数据预处理


首先,查看数据集的一些信息,为了之后能够对数据集有个清晰地认识。

import pandas as pd
df = pd.read_csv('bilibili_clean.csv')
df.info()
复制代码

image.png


输出前五行。

df.head()
复制代码

image.png


通过上图可以看到, other_data 列中包含很多数据,并不是所有的数据都对后面的分析有帮助,我们将该列拆分,只保留我们需要的列。以第一行的数据为例。

'351.52700,1,25,16777215,1601686748,0,b083a745,39082825228484615'

所需数据及含义:

  • 351.52700 :弹幕的时间位置,基于视频长度,单位秒;
  • 16777215 :弹幕颜色, 16777215 对应 0xFFFFFF
  • b083a745 :弹幕发送者的用户 id
# 将other_data列进行划分,并将需要的列添加到DataFrame中
split_df = df['other_data'].str.split(',', expand=True)
column_dict = [('video_time', 0), ('color', 3), ('user_id', 6)]
for col_name, index in column_dict:
    df[col_name] = split_df[index]
# 删除other_data列
df.drop('other_data', axis=1, inplace=True)
df.head()
复制代码

image.png

这样就得到了及结构比较清晰的数据集,我们在绘制图形前,还会对数据进行的一些处理来使的图形绘制的更加方便。


弹幕长度分布条形图


添加一列 comment_length 来记录 comment 的长度,统计 comment 各长度出现的次数。使用 pyecharts 库绘制直方图。

# 添加一列comment_length来记录comment的长度
df['comment_length'] = df['comment'].map(lambda x: len(x))
length_series = df['comment_length'].value_counts()
length_series.sort_index(ascending=True, inplace=True)
# 评论长度列表(升序)
length_list = length_series.index.astype(int).tolist()
# 各长度对应出现次数列表
count_list = length_series.values.astype(int).tolist()
# 绘制直方图
from pyecharts import options as opts
from pyecharts.charts import Bar
chart = Bar()
chart.add_xaxis(length_list).add_yaxis("第一集", count_list, color='#DF0101').set_global_opts(
        title_opts=opts.TitleOpts(title="弹幕长度分布"),
        datazoom_opts=[opts.DataZoomOpts(), opts.DataZoomOpts(type_="inside")],
    ).render("弹幕长度分布.html")
chart.render_notebook()
复制代码


image.png

观察图中信息,可以看出,随着长度的增加,弹幕的数量逐渐减少,大部分弹幕长度在10以内,这也比较符合我们的习惯,笔者发弹幕一般也是就几个字。。


弹幕颜色分布饼图


首先将十进制的颜色代码转为十六进制。之后绘制彩色代码的时候就可以按照颜色代码给扇形区域绘制对应的颜色。

import time
# 将color列的数据类型由“str”转为“int”, 数据格式由“十进制”转为“十六进制”
df['color'] = df['color'].astype(int).map(lambda x: str(hex(x)))
复制代码


统计 白色弹幕彩色弹幕 的数量,绘制饼图。

# 弹幕颜色可视化
from pyecharts.charts import Pie
color_series = df['color'].value_counts()
color_list = [color for color in color_series.index]
count_list = color_series.values.astype(int).tolist()
white_other = ['白色', '彩色']
white_other_count = [count_list[0], sum(count_list[1:])]
chart = (
    Pie()
    .add(
        "",
        [list(z) for z in zip(white_other, white_other_count)],
        radius=["40%", "75%"],
    )
    .set_colors(['#0101DF', '#FE2E2E',])
    .set_global_opts(
        title_opts=opts.TitleOpts(title="普通、彩色弹幕分布饼图"),
        legend_opts=opts.LegendOpts(orient="vertical", pos_top="15%", pos_left="2%"),
    )
    .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}"))
#     .render("pie_radius.html")
)
chart.render_notebook()
复制代码


image.png


可以看到,大部分弹幕的颜色是默认白色,虽然B站三级用户就可以发送彩色弹幕,但貌似使用的人不是很多。接下来详细看一下彩色弹幕中究竟使用的都是什么颜色? 由于颜色种类较多,这里只统计出现次数大于10次的颜色。


# 忽略出现次数小于10的颜色
for count in count_list:
    if count <= 10:
        index = count_list.index(count)
        break
new_count_list = count_list[1: index]
new_color_list = color_list[1: index]
# 将0xffffff颜色格式转为#ffffff
new_color_list = ['#' + color[2:] for color in new_color_list]
chart = (
    Pie()
    .add(
        "",
        [list(z) for z in zip(new_color_list, new_count_list)],
        radius=["40%", "75%"],
    )
    .set_colors(new_color_list)
    .set_global_opts(
        title_opts=opts.TitleOpts(title="彩色弹幕颜色分布饼图"),
        legend_opts=opts.LegendOpts(orient="vertical", pos_top="8%", pos_left="0%"),
    )
    .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}"))
#     .render("pie_radius.html")
)
chart.render_notebook()
复制代码


image.png

哇,一眼望去五颜六色的,但仔细一看,红黄占了一大半,但这也不能够表明有这么多人喜欢红黄,通过观察手机版和网页版官方提供的色号,网页版中的色号包含 #FFFF00#FE0302,手机版的暂时无法分辨,但应该是另外两个占比较多的颜色 #FEF102E70012,这些色号使用的一方面原因是用户自身的喜爱,另一方面:官方提供色号的位置可能比较靠前(狗头保命)。

image.png


弹幕量与视频内时间关系折线图


首先将 video_time 列数据类型转换为 float,然后将视频时间(共1435秒,23:55)按照10秒为间隔进行划分,0-10,10-20,20-30,30-40... ,对应标签 10,20,30,40... 。下一步,将 “秒” 类型的数据格式转为 “分:秒” ,最后统计各时间弹幕的数量。

import numpy as np
# 将video_time列的数据类型转化为float
df['video_time'] = df['video_time'].astype('float')
# 新建一个临时的DataFrame
temp_df = pd.DataFrame({})
temp_df['video_time'] = df['video_time']
# 将video_time列按照10秒一区间进行划分。
temp_df = temp_df.apply(lambda x : pd.cut(x, list(range(0, 1435, 10)) + [np.inf], labels=list(range(0, 1435, 10))))
count_series = temp_df['video_time'].value_counts()
count_series.sort_index(ascending=True, inplace=True)
# 将time数据格式由“秒”转为“分:秒”
count_series.index = count_series.index.map(lambda x: time.strftime('%M:%S', time.gmtime(x)))
time_list = count_series.index.tolist()
count_list = count_series.values.astype('int').tolist()
复制代码


根据得到的时间列表( time_list ),弹幕数量列表( count_list )绘制折线图。

# 绘制折线图
from pyecharts.charts import Line
chart = (
    Line()
    .add_xaxis(time_list)
    .add_yaxis("第一集", count_list, is_smooth=True)
    .set_series_opts(
        areastyle_opts=opts.AreaStyleOpts(opacity=0.5),
        label_opts=opts.LabelOpts(is_show=False),
    )
    .set_global_opts(
        title_opts=opts.TitleOpts(title="弹幕量与视频时间关系"),
        datazoom_opts=[opts.DataZoomOpts(), opts.DataZoomOpts(type_="inside")],
        xaxis_opts=opts.AxisOpts(
            axistick_opts=opts.AxisTickOpts(is_align_with_label=True),
            is_scale=False,
            boundary_gap=False,
        ),
    )
#     .render("line_areastyle_boundary_gap.html")
)
chart.render_notebook()
复制代码


image.png

根据视频内各个时间段发送的弹幕量,可以大致得出视频的高能时刻,就和“精彩时刻”差不多。图中峰值主要出现在开始,中间,结尾,也比较符合一般人发弹幕的时间点。


弹幕发送次数饼图


统计单用户发送弹幕次数,将弹幕发送次数分为四类,1次,2次,3次,>3次,并绘制弹幕发送次数饼图。


# 获取用户id(index)与发送弹幕次数(values)组成的series
series_user = df['user_id'].value_counts()
# 获取发送弹幕次数(index)与用户数量(values)组成的series
series_comment = series_user.value_counts()
# 对index按照升序排序
series_comment.sort_index(ascending=True, inplace=True)
# 发送弹幕次数列表
comment_count_list = series_comment.index
# 用户数量列表
user_count_list = series_comment.values.tolist()
# 将弹幕次数分为4类, 1次,2次,3次,大于3次
comment_count_list = [str(count) + '次' for count in comment_count_list[:3]] + ['>3次']
user_count_list = user_count_list[:3] + [sum(user_count_list[3:])]
chart = (
    Pie()
    .add(
        "",
        [list(z) for z in zip(comment_count_list, user_count_list)],
        center=["35%", "50%"],
    )
    .set_global_opts(
        title_opts=opts.TitleOpts(title="弹幕发送次数分布饼图"),
        legend_opts=opts.LegendOpts(pos_left="80%", orient="vertical"),
    )
    .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}"))
#     .render("pie_position.html")
)
chart.render_notebook()
复制代码

image.png


根据图中可以看到,发送一条弹幕的人占了大部分,2条的有5222个用户,3条1681个用户,大于3条的有1873个用户,接下来具体看看弹幕数量 Top10


单用户弹幕数量Top10直方图


top10 = series_comment[-10:].index.tolist()
top10.reverse()
chart = (
    Bar()
    .add_xaxis(list(range(1, 11)))
    .add_yaxis('第一集', top10, color='#F781D8')
    .set_global_opts(
        title_opts=opts.TitleOpts(title="用户发送弹幕数Top10"),
        datazoom_opts=opts.DataZoomOpts(type_="inside"),
    )
#     .render("bar_datazoom_inside.html")
)
chart.render_notebook()
复制代码

image.png

牛!!排名第一的用户,在23分钟发了76条弹幕。。平均20秒左右一条,不得不说,真的厉害,这还能够好好看视频么。不过可能是看完一遍,之后再卡时间点发弹幕的。


弹幕热词分析词云图


首先加载本地停用词库,这里根据弹幕中的词汇手动添加了一些的停用词,为了词云图的效果更好一点。

def load_stopwords(read_path):
    '''
    读取文件每行内容并保存到列表中
    :param read_path: 待读取文件的路径
    :return: 保存文件每行信息的列表
    '''
    result = []
    with open(read_path, "r", encoding='utf-8') as f:
        for line in f.readlines():
            line = line.strip('\n')  # 去掉列表中每一个元素的换行符
            result.append(line)
    return result
# 加载中文停用词
stopwords = load_stopwords('wordcloud_stopwords.txt')
复制代码


现在对弹幕中的数据进行清洗,主要去除弹幕中的空格,重复单一字符(‘111’,‘aaa’),以及时间(某某打卡)等,之后删除空字符串。

# 去除弹幕中的空格
df['comment'] = df['comment'].str.replace(r' ', '')
# 用空字符串('')替换('111','aaa','....')等
df['comment'] = df['comment'].str.replace(r'^(.)\1*$', '')
# 用空字符串('')替换('2020/11/20 20:00:00')等
df['comment'] = df['comment'].str.replace(r'\d+/\d+/\d+ \d+:\d+:\d+', '')
# 将空字符串转为'np.nan',即NAN,用于下一步删除这些弹幕
df['comment'].replace(to_replace=r'^\s*$', value=np.nan, regex=True, inplace=True)
# 删除comment中的空值,并重置索引
df = df.dropna(subset=['comment'])
df.reset_index(drop=True, inplace=True)
复制代码


清洗后,就可以使用 jieba 分词对弹幕进行分词,但分词前最好先使用 load_userdict() 导入本地的自定义词典,针对特有的领域词可以进行保留,不对其进行分词,之后剔除分词后的停用词。

import jieba
# 添加自定义词典
jieba.load_userdict("自定义词典.txt")
token_list = []
# 对弹幕内容进行分词,并将分词结果保存在列表中
for comment in df['comment']:
    tokens = jieba.lcut(comment, cut_all=False)
    token_list += [token for token in tokens if token not in stopwords]
len(token_list)
复制代码
119752


统计得到的词汇列表,取出现次数最多的前100个词,绘制词云图。

from pyecharts.charts import WordCloud
from collections import Counter
token_count_list = Counter(token_list).most_common(100)
new_token_list = []
for token, count in token_count_list:
    new_token_list.append((token, str(count)))
chart = (
    WordCloud()
    .add(series_name="热词", data_pair=new_token_list, word_size_range=[12, 88])
    .set_global_opts(
        title_opts=opts.TitleOpts(
            title="弹幕热点词云图", title_textstyle_opts=opts.TextStyleOpts(font_size=23)
        ),
        tooltip_opts=opts.TooltipOpts(is_show=True),
    )
#     .render("basic_wordcloud.html")
)
chart.render_notebook()
复制代码

image.png

刚开始绘制词云图时效果可能不太好,需要手动添加了一些词。现在看起来就还挺不错的。



相关文章
|
3天前
|
存储 前端开发
弹幕视频设计网站12------绘制弹幕02
弹幕视频设计网站12------绘制弹幕02
|
2月前
|
搜索推荐 数据可视化 Python
Matplotlib进阶:打造个性化图表
【4月更文挑战第17天】本文介绍了如何使用Matplotlib进阶功能创建个性化图表,包括自定义样式表、制作动画、实现交互式图表及整合外部库。通过`plt.style.use()`可切换样式表,自定义图表样式;利用`FuncAnimation`模块可创建动画图表展示数据变化;启用交互模式配合事件处理函数,使图表响应鼠标操作;结合Seaborn和Plotly扩展Matplotlib功能,提升图表质量和交互性。这些技巧能帮助你打造更专业、更具吸引力的数据可视化作品。
|
2月前
|
数据可视化 搜索推荐 数据挖掘
Seaborn绘图技巧:打造专业级数据可视化作品
【4月更文挑战第17天】了解Seaborn,一个基于matplotlib的Python数据可视化库,用于创建专业图表。本文重点介绍如何选择适合的图表类型,定制图表外观,进行分层和组合绘图,处理分类与顺序变量,运用调色板和颜色映射,以及结合其他库实现交互性和动态可视化。通过学习和实践,提升数据可视化技能,打造出色的数据可视化作品。
|
2月前
|
数据采集 自然语言处理 数据可视化
怎么使用Pyecharts库对淘宝数据进行可视化展示
怎么使用Pyecharts库对淘宝数据进行可视化展示
55 0
|
2月前
|
数据采集 JSON API
使用Python获取B站视频并在本地实现弹幕播放功能
使用Python获取B站视频并在本地实现弹幕播放功能
47 0
|
2月前
|
数据可视化 JavaScript 前端开发
【数据分析与可视化】pyecharts可视化图表讲解及实战(超详细 附源码)
【数据分析与可视化】pyecharts可视化图表讲解及实战(超详细 附源码)
229 0
|
9月前
|
监控 数据可视化 JavaScript
内网控制软件的数据可视化:使用D3.js创建交互式图表
在现代企业中,数据管理和可视化变得至关重要。内网控制软件的用户权限管理和监控是确保安全性的关键部分。但如何有效地管理和可视化数据呢?本文将介绍如何使用D3.js创建交互式图表,以实现内网控制软件的数据可视化。
179 1
|
数据可视化 数据挖掘 数据格式
电影数据可视化-pyecharts世界地图
电影是一种集商业性,艺术性和大众传媒性于一体的特殊人类文化产品,既是社会意识形态中的艺术现象,又是由投资,生产,销售等行为组成的经济现象。对电影榜单状况进行分析,可以更好地为电影市场的经营与管理提供依据。在电影产业蓬勃发展的当下,电影的类型,时长,流行度,发行量,影评人数票房收益和评分数据之间呈现了复杂交错的关系,在商业化背景下,电影业围绕评分和票房展开了轰轰烈烈的利益竞争,而网络评分又表明了观众在综合了思想性,艺术性等方面因素后对电影的综合评价。评分和票房双丰收标志着一部电影的良好市场口碑。为具体研究电影评分与各因素之间的因果关系,运用数据分析与挖掘技术在海量数据中发现这些隐藏的信息。
电影数据可视化-pyecharts世界地图
|
SQL 数据可视化 JavaScript
今天给大家推荐一个可视化库:cutecharts,我把她叫做pyecharts的妹妹
今天给大家推荐一个可视化库:cutecharts,我把她叫做pyecharts的妹妹
115 0
今天给大家推荐一个可视化库:cutecharts,我把她叫做pyecharts的妹妹
|
数据采集 Python
Python爬虫系列19-采集某视频中的弹幕信息
种一棵树最好的时间是十年前,其次是现在。 不管自己想做一件什么样的事情,要么全力以赴,要么果断放弃,明确对生活的态度会让一切变得更好简单。 当我们同时做很多件事情的时候,很有可能一件事情都做不好,倒不如专注的做好一件事,来的更好。
Python爬虫系列19-采集某视频中的弹幕信息