使用 Bokeh 为你的 Python 图表添加交互性

在 Bokeh 中绘图比其他一些绘图库稍微复杂一些,但额外的努力是有回报的。
100 位读者喜欢这篇文章。
Hands on a keyboard with a Python book

WOCinTech Chat。由 Opensource.com 修改。CC BY-SA 4.0

在本系列文章中,我将通过在每个库中制作相同的多条形图来研究不同 Python 绘图库的特性。这次我专注于 Bokeh(发音为“BOE-kay”)。

在 Bokeh 中绘图比在一些其他绘图库中稍微复杂一些,但额外的努力是有回报的。Bokeh 的设计目的是让您在 Web 上创建自己的交互式绘图,让您详细控制交互性的工作方式。我将通过向本系列中一直使用的多条形图添加工具提示来展示这一点。它绘制了 1966 年至 2020 年英国选举结果的数据。

A zoomed-in view on the plot

图表的放大视图(© 2019 Anvil

制作多条形图

在我们继续之前,请注意您可能需要调整您的 Python 环境才能运行此代码,包括以下内容。

  • 运行最新版本的 Python(LinuxMacWindows 的说明)
  • 验证您正在运行的 Python 版本与这些库兼容

数据在线可用,可以使用 pandas 导入

import pandas as pd
df = pd.read_csv('https://anvil.works/blog/img/plotting-in-python/uk-election-results.csv') 

现在我们准备好了。

要制作多条形图,您需要稍微处理一下您的数据。

原始数据看起来像这样

>> print(long)
        year         party  seats
0       1966  Conservative    253
1       1970  Conservative    330
2   Feb 1974  Conservative    297
3   Oct 1974  Conservative    277
4       1979  Conservative    339
..       ...           ...    ...
103     2005        Others     30
104     2010        Others     29
105     2015        Others     80
106     2017        Others     59
107     2019        Others     72

[60 rows x 3 columns]

您可以将数据视为每个可能的 (year, party) 组合的一系列 seats 值。这正是 Bokeh 的思考方式。您需要创建一个 (year, party) 元组列表

# Get a tuple for each possible (year, party) combination
x = [(str(r[1]['year']), r[1]['party']) for r in df.iterrows()]
    
# This comes out as [('1922', 'Conservative'), ('1923', 'Conservative'), ... ('2019', 'Others')]

这些将是 x 值。y 值就是席位 (seats)

y = df['seats']

现在您有了看起来像这样的数据

x                               y
('1966', 'Conservative')        253
('1970', 'Conservative')        330
('Feb 1974', 'Conservative')    297
('Oct 1974', 'Conservative')    277
('1979', 'Conservative')        339
 ...      ...                   ...
('2005', 'Others')              30
('2010', 'Others')              29
('2015', 'Others')              80
('2017', 'Others')              59
('2019', 'Others')              72

Bokeh 需要您将数据包装在它提供的一些对象中,以便它可以为您提供交互功能。将您的 x 和 y 数据结构包装在 ColumnDataSource 对象中

    from bokeh.models import ColumnDataSource

    source = ColumnDataSource(data={'x': x, 'y': y})

然后构造一个 Figure 对象,并将您的 x 数据包装在 FactorRange 对象中传入

    from bokeh.plotting import figure
    from bokeh.models import FactorRange
    
    p = figure(x_range=FactorRange(*x), width=2000, title="Election results")

您需要让 Bokeh 创建一个颜色映射 (colormap)——这是一个特殊的 DataSpec 字典,它从您给定的颜色映射中生成。在本例中,颜色映射是政党名称和十六进制值之间的简单映射

    from bokeh.transform import factor_cmap

    cmap = {
        'Conservative': '#0343df',
        'Labour': '#e50000',
        'Liberal': '#ffff14',
        'Others': '#929591',
    }
    fill_color = factor_cmap('x', palette=list(cmap.values()), factors=list(cmap.keys()), start=1, end=2)

现在您可以创建条形图了

    p.vbar(x='x', top='y', width=0.9, source=source, fill_color=fill_color, line_color=fill_color)

Bokeh 图表上的数据可视化表示被称为 glyphs,因此您创建了一组条形 glyphs。

调整图形的细节,使其看起来符合您的要求

    p.y_range.start = 0
    p.x_range.range_padding = 0.1
    p.yaxis.axis_label = 'Seats'
    p.xaxis.major_label_orientation = 1
    p.xgrid.grid_line_color = None

最后,告诉 Bokeh 您现在想看到您的图表

   from bokeh.io import show

   show(p)

这会将图表写入 HTML 文件并在默认 Web 浏览器中打开。结果如下

A multi-bar plot in Bokeh

Bokeh 中的多条形图(© 2019 Anvil

这已经有一些交互功能,例如框缩放

Bokeh's built-in box zoom

Bokeh 的内置框缩放(© 2019 Anvil

但 Bokeh 的伟大之处在于您可以添加自己的交互性。在下一节中通过向条形图添加工具提示来探索这一点。

向条形图添加工具提示

要向条形图添加工具提示,您只需要创建一个 HoverTool 对象并将其添加到您的图形中

    h = HoverTool(tooltips=[
        ('Seats', '@y'),
        ('(Year, Party)', '(@x)')
    ])
    p.add_tools(h)

参数定义了工具提示上显示的数据。变量 @y@x 指的是您传递给 ColumnDataSource 的变量。您可以使用其他一些值;例如,光标在图表上的位置由 $x$y 给出(与 @x@y 无关)。

结果如下

The election graph, now with tooltips

选举图表,现在带有工具提示(© 2019 Anvil

得益于 Bokeh 的 HTML 输出,当您将图表嵌入 Web 应用程序时,您可以获得完整的交互体验。您可以在此处将此示例复制为 Anvil 应用程序 here(注意:Anvil 需要注册才能使用)。

现在您可以看到为什么需要额外努力将所有数据包装在 Bokeh 中的对象中,例如 ColumnDataSource。作为回报,您可以相对轻松地添加交互性。

回归简洁:Altair

Bokeh 是最流行的四个绘图库之一,本系列正在研究是什么让它们各自特别

我还将研究一些因其有趣的方法而脱颖而出的库。接下来,我将研究 Altair,其声明式 API 意味着它可以制作非常复杂的图表而不会引起脑筋疲劳。


本文基于 Anvil 博客上的《How to make plots using Bokeh》一文,并已获得许可重复使用。

接下来阅读
User profile image.
Shaun 开始认真编程,通过模拟世界最大激光系统中的燃烧聚变等离子体。他爱上了 Python 作为数据分析工具,并且从未回头。现在他想把一切都变成 Python。

贡献者

2 条评论

Plotly 可以生成交互式图表,对吗? 我可以直接用 Plotly 做吗?

你能展示一下如何获取原始的长数据框吗?

Creative Commons License本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。
© . All rights reserved.