【数据可视化】Python中使用Bokeh进行数据可视化,第一部分:入门

提升您的可视化游戏

如果没有有效的方法来传达结果,最复杂的统计分析可能毫无意义。最近我在研究项目中的经验使我们利用数据科学来提高建筑能效,从而推动了这一点。在过去的几个月里,我的一个团队成员一直致力于一种称为小波变换的技术,该技术用于分析时间序列的频率成分。该方法取得了积极的成果,但她在解释它时遇到了麻烦而没有迷失在技术细节中。

被激怒了,她问我是否可以通过视觉展示转变。在几分钟内使用一个名为ř的软件包gganimate,我制作了一个简单的动画,展示了该方法如何转换时间序列。现在,我的团队成员可以显示剪辑,而不是努力解释小波,而是直观地了解该技术的工作原理。我的结论是我们可以做最严格的分析,但在一天结束时,所有人都希望看到的是一个GIF!虽然这个陈述是幽默的,但它有一个真实要素:如果不能清楚地传达结果将产生很小的影响,并且通常用可视化来呈现分析结果的最佳方式。

可用于数据科学的资源正在迅速发展,这在可视化领域尤其明显似乎每周都有另一种选择。随着所有这些进步,有一个共同的趋势:增加交互性。人们喜欢在静态图中查看数据,但他们更喜欢的是使用数据来查看更改参数如何影响结果。关于我的研究,一份报告告诉建筑物所有者他们可以通过改变他们的交流时间表节省多少电力是很好的,但是给他们一个交互式图表更有效,他们可以选择不同的时间表,看看他们的选择如何影响用电量。最近,受到互动情节趋势的启发以及不断学习新工具的渴望,我一直在与Bokeh合作,一个Python库。我为我的研究项目构建的仪表板中显示了Bokeh交互功能的一个示例:

虽然我不能分享这个项目背后的代码,但我可以通过一个使用公开数据构建完全交互式Bokeh应用程序的例子。本系列文章将介绍使用Bokeh创建应用程序的整个过程。对于第一篇文章,我们将介绍Bokeh的基本元素,我们将在后续文章中对其进行构建。在本系列中,我们将使用nycflights13数据集,该数据集记录了2013年超过300,000个航班。我们将首先专注于可视化单个变量,在这种情况下,航班的到达延迟时间为几分钟,我们将从构造基本直方图,一种显示一个连续变量的传播和位置的经典方法。该完整的代码是在GitHub上访问第一个Jupyter笔记本可以在这里找到。这篇文章重点关注视觉效果,所以我鼓励任何人查看代码,如果他们想看到数据清理和格式化的无耻但必要的步骤!

 

Bokeh的基础知识

Bokeh的主要概念是图形一次构建一层。我们首先创建一个图形,然后在图形中添加称为字形的元素。(对于那些使用过ggplot的人来说,字形的概念基本上与一次添加到图形中的一个'图层'的geoms相同。)字形可以根据所需的用途呈现多种形状:圆形,线条,补丁,条形,弧形等。让我们通过制作带有正方形和圆形的基本图表来说明字形的概念。首先,我们使用该figure方法创建一个绘图,然后通过调用适当的方法并传入数据将我们的字形附加到绘图中。最后,我们展示了我们的情节(我正在使用一个Jupyter Notebook,它可以让你看到代码下面的图表,如果你使用这个output_notebook调用)。

#背景虚化基础
from bokeh.plotting import figure
from bokeh.io import show, output_notebook

#创建带标签的空白图
p = figure(plot_width = 600, plot_height = 600, 
           title = 'Example Glyphs',
           x_axis_label = 'X', y_axis_label = 'Y')

#示例数据
squares_x = [1, 3, 4, 5, 8]
squares_y = [8, 7, 3, 1, 10]
circles_x = [9, 12, 4, 3, 15]
circles_y = [8, 4, 11, 6, 10]

#添加方块
p.square(squares_x, squares_y, size = 12, color = 'navy', alpha = 0.6)
#添加圆圈字形
p.circle(circles_x, circles_y, size = 12, color = 'red')

#设置输出笔记本中的绘图
output_notebook()
# Show the plot
show(p)

这会产生下面略显无趣的图:

虽然我们可以在任何绘图库中轻松制作此图表,但我们可以免费获得一些工具,其中包含右侧的任何Bokeh图,包括平移,缩放,选择和绘图保存功能。这些工具是可配置的,在我们想要调查我们的数据时会派上用场。

现在让我们开始展示我们的航班延误数据。在我们可以直接进入图表之前,我们应该加载数据并给它一个简短的检查(粗体是代码输出):

# Read the data from a csv into a dataframe
flights = pd.read_csv('../data/flights.csv', index_col=0)
# Summary stats for the column of interest
flights['arr_delay'].describe()

count 327346.000000 
mean 6.895377 
std 44.633292 
min -86.000000 
25%-17.000000 
50%-5.000000 
75%14.000000 
max 1272.000000

 

摘要统计数据为我们提供了信息,可以为我们的策划决策提供信息:我们有327,346次航班,最短延误时间为-86分钟(意味着航班提前86分钟),最长延迟时间为1272分钟,惊人的21小时!75%的分位数仅在14分钟,因此我们可以假设超过1000分钟的数字可能是异常值(这并不意味着它们是非法的,只是极端的)。我将重点关注直方图在-60分钟到+120分钟之间的延迟。

直方图是针对单个变量的初始可视化共同的选择,因为它示出了数据的分布。x位置是被分组为称为区间的区间的变量的值,并且每个条的高度表示每个区间中的数据点的计数(数量)。在我们的例子中,x位置将代表以分钟为单位的到达延迟,高度是相应仓位中的航班数量。Bokeh没有内置的直方图字形,但是我们可以使用quad字形来制作我们自己的字形,这允许我们指定每个条形的底部,顶部,左侧和右侧边缘。

要为条形图创建数据,我们将使用numpy histogram函数计算每个指定bin中的数据点数。我们将使用5分钟长度的箱子,这意味着该功能将计算每五分钟延迟间隔的航班数量。在生成数据之后,我们将其放入pandas数据帧中以将所有数据保存在一个对象中。这里的代码对于理解Bokeh并不重要,但它仍然有用,因为数据科学中的numpy和pandas普遍存在!

"""Bins will be five minutes in width, so the number of bins 
is (length of interval / 5). Limit delays to [-60, +120] minutes using the range."""
arr_hist, edges = np.histogram(flights['arr_delay'], 
                               bins = int(180/5), 
                               range = [-60, 120])
# Put the information in a dataframe
delays = pd.DataFrame({'arr_delay': arr_hist, 
                       'left': edges[:-1], 
                       'right': edges[1:]})

我们的数据如下:

flights柱是来自每个延迟间隔内的航班数量的计数leftright。从这里开始,我们可以创建一个新的Bokeh图形并添加一个指定适当参数的四元组glpyh:

# Create the blank plot
p = figure(plot_height = 600, plot_width = 600, 
           title = 'Histogram of Arrival Delays',
          x_axis_label = 'Delay (min)]', 
           y_axis_label = 'Number of Flights')

# Add a quad glyph
p.quad(bottom=0, top=delays['flights'], 
       left=delays['left'], right=delays['right'], 
       fill_color='red', line_color='black')

# Show the plot
show(p)

生成此图表的大部分工作都来自数据格式化,这在数据科学中并不罕见!从我们的情节来看,我们看到到达延迟几乎正常分布,右侧轻微的正偏斜或重尾。

有更简单的方法可以在Python中创建基本直方图,并且可以使用几行来完成相同的结果matplotlib。然而,Bokeh图所需的开发收益来自于与我们现在可以轻松添加到图表中的数据交互的工具和方式。

 

增加交互性

我们将在本系列中介绍的第一种交互方式是被动交互。这些是观众可以采取的动作,不会改变显示的数据。这些被称为检查员,因为它们允许观众更详细地“调查”数据。一个有用的检查器是当用户将鼠标悬停在数据点上时出现的工具提示,在Bokeh中称为HoverTool

为了添加工具提示,我们需要将数据源从数据帧更改为ColumnDataSource,这是Bokeh中的一个关键概念。这是一个专门用于绘图的对象,包括数据以及多个方法和属性。ColumnDataSource允许我们为图形添加注释和交互性,并且可以从pandas数据框构建。实际数据本身保存在可通过ColumnDataSource的data属性访问的字典中。在这里,我们从数据框创建源,并查看数据字典的键,这些键对应于数据帧的列。

# Import the ColumnDataSource class
from bokeh.models import ColumnDataSource
# Convert dataframe to column data source
src = ColumnDataSource(delays)
src.data.keys()
dict_keys(['flights', 'left', 'right', 'index'])

当我们使用ColumnDataSource添加字形时,我们传入ColumnDataSource作为source参数并使用字符串引用列名:

# Add a quad glyph with source this time
p.quad(source = src, bottom=0, top='flights', 
       left='left', right='right', 
       fill_color='red', line_color='black')

 

请注意代码如何通过单个字符串而不是df['column']之前的格式引用特定数据列,例如“flight”,“left”和“right” 。

 

在Bokeh的HoverTool

HoverTool的语法起初可能看起来有点复杂,但通过练习它们很容易创建。我们通过我们的HoverTool实例的列表tooltipsPython的元组,其中第一元素是数据和第二参考我们要突出具体数据的标签。我们可以使用'$'引用图表的任一属性,例如x或y位置,或使用'@'引用我们的源中的特定字段。这可能听起来有点令人困惑所以这里是一个HoverTool的例子,我们两个都做:

# Hover tool referring to our own data field using @ and
# a position on the graph using $
h = HoverTool(tooltips = [('Delay Interval Left ', '@left'),
                          ('(x,y)', '($x, $y)')])

这里,我们left 使用'@'引用ColumnDataSource中的数据字段(对应于原始数据帧的'left'列),并使用'$'引用光标的(x,y)位置。结果如下:

(x,y)位置是图表上鼠标的位置,对我们的直方图没有多大帮助,因为我们要找到给定条形中对应于条形顶部的飞行数。为了解决这个问题,我们将改变我们的工具提示实例以引用正确的列。格式化工具提示中显示的数据可能会令人沮丧,因此我通常会在数据框中使用正确的格式创建另一列。例如,如果我希望我的工具提示显示给定条的整个间隔,我在我的数据框中创建一个格式化的列:

# Add a column showing the extent of each interval
delays['f_interval'] = ['%d to %d minutes' % (left, right) for left, right in zip(delays['left'], delays['right'])]

然后我将此数据帧转换为ColumnDataSource并在我的HoverTool调用中访问此列。以下代码使用悬停工具创建绘图,引用两个格式化的列并将工具添加到绘图中:

# Create the blank plot
p = figure(plot_height = 600, plot_width = 600, 
           title = 'Histogram of Arrival Delays',
          x_axis_label = 'Delay (min)]', 
           y_axis_label = 'Number of Flights')

# Add a quad glyph with source this time
p.quad(bottom=0, top='flights', left='left', right='right', source=src,
       fill_color='red', line_color='black', fill_alpha = 0.75,
       hover_fill_alpha = 1.0, hover_fill_color = 'navy')

# Add a hover tool referring to the formatted columns
hover = HoverTool(tooltips = [('Delay', '@f_interval'),
                             ('Num of Flights', '@f_flights')])

# Style the plot
p = style(p)

# Add the hover tool to the graph
p.add_tools(hover)

# Show the plot
show(p)

在Bokeh样式中,我们通过将元素添加到原始图形中来包含元素。在通知p.quad字形电话,还有一些额外的参数,hover_fill_alpha并且hover_fill_color,它们可以更改字形,当我们的鼠标移到栏的外观。我还使用style 函数添加了样式(请参阅笔记本中的代码)。美学是很乏味的类型,所以我通常写一个函数,我可以应用于任何情节。当我使用样式时,我会保持简单并专注于标签的可读性。图的主要观点是显示数据,添加不必要的元素只会减少图形的用处!最终的情节如下:

当我们将鼠标悬停在不同的栏上时,我们会获得该栏的精确统计数据,显示该区间内的间隔和航班数。如果我们为我们的情节感到自豪,我们可以将其保存到html文件中进行分享:

# Import savings function
from bokeh.io import output_file
# Specify the output file and save
output_file('hist.html')
show(p)

 

进一步的步骤和结论

我花了不止一个图来获得Bokeh的基本工作流程,所以如果有很多需要学习的话,不要担心。我们将在本系列课程中获得更多练习!虽然看起来Bokeh的工作量很大,但当我们想要将视觉效果扩展到简单的静态数字之外时,其好处就来了。一旦我们有了基本图表,我们就可以通过添加更多元素来提高视觉效果。例如,如果我们想查看航空公司的到达延误,我们可以制作一个交互式图表,允许用户选择和比较航空公司。我们会将那些改变所显示数据的主动互动留给下一篇文章,但这里是我们可以做的:

主动交互需要更多涉及脚本,但这使我们有机会使用我们的Python!(如果有人想在下一篇文章之前看一下这个剧情的代码,这里就是。)

在本系列文章中,我想强调的是,Bokeh或任何一个库工具永远不会成为满足您所有绘图需求的一站式工具。Bokeh非常适合允许用户浏览图形,但对于其他用途,例如简单的探索性数据分析,轻量级库matplotlib可能会更高效。本系列旨在展示Bokeh的功能,为您提供您可以根据需要依赖的另一个绘图工具。您知道的库越多,就越有能力使用正确的可视化工具完成任务。

 

原文:https://towardsdatascience.com/data-visualization-with-bokeh-in-python-part-one-getting-started-a11655a467d4

 

猜你喜欢

转载自blog.csdn.net/ChenVast/article/details/83536720