手把手教你用Bokeh进行可视化数据分析(附源码)
点击上方“Python数据科学”,选择“星标公众号”
关键时刻,第一时间送达!
▍前言
上一篇利用交互式可视化分析了一下金州勇士队4年3冠的原因,其中数据处理部分使用了numpy和pandas,可视化部分使用的是Bokeh和Plotly,效果非常赞,链接如下:
上一篇文章一些朋友留言想要源码学习一下,应大家要求,本篇就分享一下如何使用Bokeh进行一系列炫酷的数据可视化分析。
Bokeh与Python可视化领域中的流行库Matplotlib和Seaborn不同,它使用HTML和JavaScript渲染其图形,这使得它在构建基于Web的应用中成为一个非常理想的候选者。它对于探索和理解数据,或创建漂亮的项目报告自定义图表,非常有帮助。
上一篇大家也看到了这些交互式图表,非常炫酷,且易于分析和观察。
连续比赛胜负的技术指标追踪
胜场中二分球与三分球命中率的关系
本篇总结了Bokeh的使用步骤,并将带你从零开始学会使用Bokeh,并最终实现像上面一样高大尚的数据可视化交互式图表。看完本篇你将学会:
使用Bokeh可视化数据
自定义和组织可视化
为可视化添加交互性
▍Bokeh的使用步骤
Bokeh在使用上有一个固定的操作顺序,因此,只要你熟悉了这个流程(模板),就可以快速了解并入门Bokeh了,主要有以下几个重要的步骤:
准备数据
确定可视化的呈现位置
配置图形界面
连接并绘制数据
组织布局
预览并保存数据创建
以上6个步骤构成了一个简洁,灵活的模板,下面我们来看一下与模板对应的代码:
"""Bokeh 可视化模板
这个模板是一个通用的框架步骤,可以让你通过使用Bokeh
把数据转化为可视化效果
"""
# 数据处理库
import pandas as pd
import numpy as np
# Bokeh库
from bokeh.io import output_file, output_notebook
from bokeh.plotting import figure, show
from bokeh.models import ColumnDataSource
from bokeh.layouts import row, column, gridplot
from bokeh.models.widgets import Tabs, Panel
# 步骤一:准备数据
# 步骤二:决定数据可视化的呈现位置
output_file('filename.html') # 生成一个静态HTML文件,
output_notebook() # 在Jupyter Notebook中内联呈现
# 步骤三:设置图形
fig = figure() # 实例化一个 figure() 对象
# 步骤四:连接并绘制数据
# 步骤五:组织布局
# 步骤六:预览和保存
show(fig) # 查看已做的,并保存喜欢的
下面将详细地解释上面提到的每一个步骤:
步骤 1:准备数据
此步骤通常涉及Pandas和Numpy等数据处理库的使用,并且会采取必要的步骤将其转换为最适合我们预期可视化的形式。
步骤 2:确定可视化的呈现位置
在此步骤中,你将确定如何生成并最终查看可视化。Bokeh提供了两个常见选项:(1) 生成静态的HTML文件,(2) 在Jupyter Notebook中内联呈现可视化。
步骤 3:配置图形界面
你将配置图形,为可视化准备画布。在此步骤中,你可以自定义比如标题,刻度线等的所有内容,你还可以设置一组工具,以便与你的可视化进行各种用户交互。
步骤 4:连接并绘制数据
接下来,你将使用Bokeh的渲染器(可视化图)来塑造数据。在这里,你可以灵活地使用许多可用的标记和形状选项从头开始绘制数据,所有这些都可以轻松定制,有极高的创作自由。
此外,Bokeh还具有一些内置功能,可用于构建堆积条形图等大量示例,以及用于创建网络图和地图等更高级可视化的大量示例。
步骤 5:组织布局
如果你需要多个图来表达数据,那么Bokeh也将会提供很好的帮助。Bokeh不仅提供了标准的网格状布局选项,而且还允许你使用几行代码轻松地将可视化组织为选项卡式可切换的布局。
此外,所有绘图可以快速连接在一起,如果手动选择其中一个,也必将会反映在与已连接的其它任何组合上。
步骤 6:预览并保存数据创建
无论是在浏览器还是notebook中查看可视化,都可以浏览可视化,检查自定义,以及使用添加的任何交互。如果对其中的某个很喜欢,还可以将可视化文件保存到图像文件中。
下面我们将基于上面6个步骤一步一步地实现一个精美的可视化效果。数据集与上一篇一样,来源于Kaggle,链接如下:
https://www.kaggle.com/pablote/nba-enhanced-stats
▍从零开始使用Bokeh实现可视化
下面我们开始按照Bokeh的使用步骤对处理数据进行可视化。
步骤 1:准备数据
在进行可视化之前我们先使用pandas对原始数据进行一些提取和处理操作,生成DataFrame数据表结构。
# Bokeh库
from bokeh.plotting import figure, show
from bokeh.io import output_file
from bokeh.models import ColumnDataSource, CategoricalColorMapper, NumeralTickFormatter
from bokeh.layouts import gridplot
import pandas as pd
# 读取csv文件
team_stats = pd.read_csv('2017-18_teamBoxScore.csv',
parse_dates=['gmDate'])
# 提取相关数据
gs_gm_stats_2 = (team_stats[(team_stats['teamAbbr'] == 'GS') &
(team_stats['seasTyp'] == 'Regular')]
.loc[:, ['gmDate',
'team2P%',
'team3P%',
'teamPTS',
'opptPTS']]
.sort_values('gmDate'))
# 添加比赛号码
gs_gm_stats_2['game_num'] = range(1, len(gs_gm_stats_2) + 1)
# 衍生出一个新的 “输赢” 列特征
win_loss = []
for _, row in gs_gm_stats_2.iterrows():
# 如果勇士队得分更多,判定为赢
if row['teamPTS'] > row['opptPTS']:
win_loss.append('W')
else:
win_loss.append('L')
# 添加输赢特征(winLoss)
gs_gm_stats_2['winLoss'] = win_loss
如上所示,首先从数据表筛选出勇士队,且为常规赛,接着筛选出比赛日期,队伍两分球,三分球,队伍得分,对手得分等列特征,最后组成一个新表。然后,对数据表添加比赛号码和衍生出来的特征winLoss。数据处理后可以得到以下的结果(示例前5行):
当我们谈到Python中的数据时,很可能会遇到Python的dict和Pandas的 DataFrames数据结构,尤其是当从文件或外部数据源读取数据时。Bokeh可以很好地处理这些更为复杂的数据结构,甚至还有一个内置的功能来处理它们,就是ColumnDataSource。
你可能会问:“Bokeh可以直接使用其他数据类型,为什么要使用ColumnDataSource? ”
首先,无论你是直接引用列表,数组,字典还是DataFrame,Bokeh都会自己将其转换为ColumnDataSource。简单理解就是,它会使得实现Bokeh的交互式功能更加容易。其主要功能是将数据结构的名称(比如字典的key,或者dataframe的column)映射到数据列,这使得在构建可视化时更容易引用数据元素。ColumnDataSource可以解释三种类型的数据对象:
Python dict:键是与相应值序列(列表,数组等)相关联的名称。
Pandas DataFrame:DataFrame的列成为ColumnDataSource的引用名称。
Pandas groupby:ColumnDataSource的列会引用通过调用groupby.describe()看到的列。
明白了它的用处,我们直接把上面已处理好的phi_gm_stats_2储存在ColumnDataSource中,代码如下:
# 步骤一:将数据储存在ColumnDataSource中
gm_stats_cds = ColumnDataSource(phi_gm_stats_2)
步骤 2:确定可视化的呈现位置
在Bokeh中输出可视化的方法有以下两个选项:
output_file('filename.html'):将可视化文件写入静态HTML文件
output_notebook():将直接在Jupyter Notebook中呈现你的可视化
注意,这两个函数在调用show()之后才会有效果。
如果在一次执行中同时调用了output_file()和output_notebook(),两种可视化将会同时出现。但是,如果由于某种原因在一次执行中运行了多个output_file()命令,则只有最后一个命令将用于呈现。我们这里选择生成一个静态的html文件,因此,如果你运行代码后,会有一个新的窗口弹出,代码如下:
# 步骤二:生成一个静态的html文件
output_file('gs-gm-linked-selections.html',
title='Golden State Percentages vs. Win-Loss')
步骤 3:配置图形界面
我们想看一下勇士队队2017-18年常规赛里的 “两分球得分率和三分球命中率的关系”,以及“本球队伍得分与对手得分的关系”。
我们首先将使用两次figure()实例化来分别配置两个关系图形界面,通过一些参数设置来达到目标可视化效果。其中,toolList参数是一个自定义的工具列表,列表元素由自己选择,比如通过引入lasso_select,我们就可以交互式地自由选择数据范围(最终效果我们会在后面看到)。
# 自定义工具
toolList = ['lasso_select', 'tap', 'reset', 'save']
# 步骤三:配置图形界面
pctFig = figure(title='两分球得分率 % vs 3分球得分率 %, 2017-18 常规赛季',
plot_height=400, plot_width=400, tools=toolList,
x_axis_label='两分球得分率%', y_axis_label='3分球得分率%')
# 创建一个与整体相关的图形
totFig = figure(title='团队得分 vs 对手得分, 2017-18 常规赛季',
plot_height=400, plot_width=400, tools=toolList,
x_axis_label='团队得分', y_axis_label='对手得分')
步骤 4:连接并绘制数据
上面我们通过实例化得到了pctFig和totFig,接着我们对pctFig选择使用圆点图来绘制数据,对totFig选择使用方形点图来绘制数据,具体代码如下:
# 步骤四:采用圆点图绘制数据
pctFig.circle(x='team2P%', y='team3P%', source=gm_stats_cds,
size=12, color='black')
# 将y轴标记变为百分比形式
pctFig.xaxis[0].formatter = NumeralTickFormatter(format='00.0%')
pctFig.yaxis[0].formatter = NumeralTickFormatter(format='00.0%')
# 创建CategoricalColorMapper,对win和loss分配特定颜色
win_loss_mapper = CategoricalColorMapper(factors = ['W', 'L'],
palette=['Green', 'Red']) # 绘制正方形点图
totFig.square(x='teamPTS', y='opptPTS', source=gm_stats_cds, size=10,
color=dict(field='winLoss', transform=win_loss_mapper))
拿pctFig圆点图举例,x为特征team2P%,y为特征team3P%,source代表这两个特征列的来源,即gm_stats_cds,size大小为12,color为black。通过这个参数设置看出,我们可以直接简单地引用特征列名称,并设置特征列来源来完成参数配置,来很好地表达数据。
totFig正方形点图中,参数color通过CategoricalColorMapper进行配置,将green代表胜利,red代表失败。然后使用dict将颜色配置映射到winLoss特征上。
步骤 5:组织布局
图形绘制完毕,我们想将两个绘图进行布局。Bokeh中,可以是使用网格式布局,或者选项卡切换式的布局。这里我们使用网格式布局,通过gridplot来完成,元素是一个包含上面图形实例的列表。
# 创建图形布局
grid = gridplot([[pctFig, totFig]])
步骤 6:预览并保存数据创建
最后,我们通过Bokeh的show来对整个图形布局进行预览。
# 可视化展示
show(grid)
如果运行没有问题,那么将会创建一个新的浏览器窗口,然后出现我们的可视化图形。
可以看到,图像右上角有一个工具条选项,有套索,单击,刷新,保存。我们主要看一下套索和单击是如何操作的。
套索
在套索模式下,我们在左图中随意地选择一个范围,可以看到在右图自动地出现了对应的数据点。
单击
在单击模式下,我们只能单个地挑选某一个点(即某一场比赛),然后可以通过高亮来清洗的观察和比较分析。比如下图中,我们随机在左图选择一个点,也会在右图自动地出现相应的点。
▍其它交互可视化效果
除了上面套索工具的交互式效果以外,还有很多其他非常棒的工具,比如滑动,高亮等等。如果大家感兴趣可以自行尝试,由于篇幅问题,本篇只分享其中一种用法,下面展示其它几个交互式动态图的示例:
滑动
从上面动态图可以很清晰地看出随着比赛场次增加,胜负场的分布情况,以及对应的得分,篮板,助攻和失误的技术指标追踪。这样可以看出球队在某一段时间内的具体表现如何,比如连续出现红色(失败),说明球队持续低迷,需要查找原因,看是失误多造成的,还是篮板少造成的,并根据这些数据对球员进行加强训练。
高亮
https://realpython.com/python-data-visualization-bokeh/
通过高亮,我们对比了 “勒布朗.詹姆斯” 和 “凯文.杜兰特” 的得分和篮板关系情况。这种定向比较可以发掘各个球队核心球员的综合能力和实力差距。
从上面可以看出:两位巨头得分平均大约都在30+,篮板也差不多场均10左右。就整体而言,二位巨头实力相当,但詹皇个人能力会稍微胜出一点,偶尔会打出非常惊人的成绩,比如得分50+,篮板16+等,而杜兰特虽没有太多的超水平发挥,但数据比较集中,发挥相对比较稳定。
▍总结
以上通过一个实际案例介绍了Bokeh的使用,其它的还有很多非常强大的交互式可视化库可以使用,比如plotly等,如果感兴趣可以参考官网进行深入学习研究。本篇完整代码和数据集在后台回复:勇士队
Python数据科学【读者福利】 ↓↓↓
往期精彩推荐 ↓↓↓
【1】10个Python常见面试题,这些弄不明白不要说学过Python!