Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

第一章:快速入门

本章目标:用一个最小但完整的例子跑通 Bokeh,理解它适合解决什么问题,并知道下一步该学习哪些概念。

延伸阅读:本章只介绍 Bokeh 的基本用法。ColumnDataSource 的深入讲解见第二章 2.2FigureGlyph 的关系见第二章 2.3;三层接口的详细说明见第二章 2.4;输出选项的完整讨论见第八章;如果你想先建立对不同运行方式的整体认识,也可以先浏览第八章 8.1第七章 7.1

1.1 从一个需求开始

假设你有一组销售数据,想要展示每天的销售额变化。用 Matplotlib 可以很快画出一张静态图:

import matplotlib.pyplot as plt

days = [1, 2, 3, 4, 5]
sales = [100, 150, 120, 180, 200]

plt.plot(days, sales)
plt.savefig("sales.png")

这类图片很适合放进论文、报告或幻灯片。但如果你的需求变成下面这样,静态图片就不够方便了:

  • 想在浏览器里缩放和平移,查看局部细节
  • 想把鼠标悬停在点上,显示具体数值
  • 想生成一个可以直接分享的 HTML 文件
  • 想把图表嵌入现有 Web 页面或数据应用
  • 想后续扩展为可筛选、可联动、可实时更新的仪表板

这就是 Bokeh 的典型使用场景:

用 Python 构建原生 Web 交互图表,并输出到浏览器、HTML 文件、Notebook 或 Web 应用中。

需要注意的是,Matplotlib 也有交互式后端,并不是“完全不能交互”。Bokeh 的优势在于:它以浏览器和 Web 交互为核心设计,生成的是由 BokehJS 渲染的交互式图表,更适合分享、嵌入和构建数据应用。

1.2 安装与环境

系统要求

本教程面向 Bokeh 3.x 编写。建议使用:

  • Python 3.10 或更高版本
  • 推荐 Python 3.11+,以获得更好的生态兼容性和运行性能
  • 一个现代浏览器,例如 Chrome、Firefox、Edge 或 Safari

基础安装

如果你使用 pip

pip install bokeh

验证安装:

python -c "import bokeh; print(bokeh.__version__)"

如果你使用 conda

conda install bokeh

可选依赖

Bokeh 的基础绘图不需要安装额外依赖。但有些功能需要额外包,例如导出 PNG/SVG、使用 Notebook 小组件或处理更复杂的应用场景。

常见选择:

# 安装 Bokeh 的常用可选依赖
pip install "bokeh[all]"

# 如果你需要在 Jupyter 中使用更完整的 Bokeh 小组件支持
pip install jupyter_bokeh

提示:如果你只是想在 Notebook 中显示普通 Bokeh 图表,通常先从 output_notebook() 开始即可;如果遇到 JupyterLab 显示或小组件相关问题,再安装 jupyter_bokeh

1.3 第一个 Bokeh 图表

下面用同一组销售数据生成一个交互式 HTML 图表:

from bokeh.plotting import figure, output_file, show

days = [1, 2, 3, 4, 5]
sales = [100, 150, 120, 180, 200]

output_file("sales.html", title="销售趋势")

p = figure(
    title="销售趋势",
    x_axis_label="日期",
    y_axis_label="销售额",
    width=700,
    height=400,
    tools="pan,wheel_zoom,box_zoom,reset,save",
    active_scroll="wheel_zoom",
)

p.line(days, sales, line_width=2, legend_label="销售额")
p.scatter(days, sales, size=8, legend_label="销售额")

show(p)

运行后,Bokeh 会生成 sales.html,并在浏览器中打开它。你可以:

  • 使用滚轮缩放图表
  • 拖拽平移查看不同区域
  • 使用框选缩放查看局部范围
  • 点击重置按钮恢复初始视图
  • 点击保存按钮下载当前图表为图片

这段代码可以拆成三步理解:

  1. output_file("sales.html"):指定输出目标是一个 HTML 文件
  2. figure(...):创建一张图,并配置标题、坐标轴、尺寸和工具栏
  3. p.line(...)p.scatter(...):向图中添加具体图形
  4. show(p):保存并打开图表

这就是 Bokeh 最常见的工作流:

准备数据 → 创建 Figure → 添加 Glyph → 输出或展示图表。

其中 Figure 是整张图的容器,linescatter 添加的是具体图形元素,也就是 Bokeh 中常说的 Glyph。这些概念会在第二章展开。

1.4 加上悬停提示

交互图表最常见的需求之一是:鼠标移动到数据点上时显示更多信息。

这时推荐使用 ColumnDataSource。它是 Bokeh 中最重要的数据结构之一,可以把数据组织成“按列存储的表”。

from bokeh.models import ColumnDataSource, HoverTool
from bokeh.plotting import figure, output_file, show

source = ColumnDataSource(data={
    "day": [1, 2, 3, 4, 5],
    "sales": [100, 150, 120, 180, 200],
    "note": ["周一", "周二", "周三", "周四", "周五"],
})

output_file("sales_with_hover.html", title="销售趋势")

p = figure(
    title="销售趋势",
    x_axis_label="日期",
    y_axis_label="销售额",
    width=700,
    height=400,
    tools="pan,wheel_zoom,box_zoom,reset,save",
    active_scroll="wheel_zoom",
)

p.line("day", "sales", source=source, line_width=2)
p.scatter("day", "sales", source=source, size=8)

hover = HoverTool(tooltips=[
    ("日期", "@day"),
    ("销售额", "@sales"),
    ("说明", "@note"),
])
p.add_tools(hover)

show(p)

注意这段代码中的两个变化:

  • 图形方法里不再直接写列表,而是写列名,例如 "day""sales"
  • HoverTool 通过 @day@sales@note 读取同一行中的字段

如果你后续要做筛选、联动、回调或实时更新,ColumnDataSource 会变得非常重要。现在只需要先记住一句话:

简单图表可以直接传列表;一旦涉及交互和多字段数据,优先使用 ColumnDataSource

1.5 在 Jupyter 中使用

如果你在 Jupyter Notebook 或 JupyterLab 中学习 Bokeh,可以把输出目标切换到 Notebook:

from bokeh.io import output_notebook, show
from bokeh.plotting import figure

output_notebook()

p = figure(title="Notebook 中的 Bokeh 图表", width=600, height=350)
p.line([1, 2, 3, 4, 5], [100, 150, 120, 180, 200], line_width=2)
p.scatter([1, 2, 3, 4, 5], [100, 150, 120, 180, 200], size=8)

show(p)

常见输出方式如下:

输出方式适用场景特点
output_notebook()Jupyter 开发和教学图表直接显示在 Notebook 单元格中
output_file()生成独立 HTML 文件适合本地查看、分享和归档
save()程序化保存只保存文件,不自动打开浏览器
show()快速预览根据当前输出目标显示图表
components()嵌入 Web 页面返回可嵌入网页的 HTML/JavaScript 片段

更完整的输出方式会在第八章介绍。

1.6 先建立一个概念:Bokeh 的四种运行模式

很多初学者一开始最容易混淆的,不是 figure()HoverTool,而是:

同样是 Bokeh 代码,为什么有的可以直接生成 HTML,有的必须用 bokeh serve 运行?

你可以先把 Bokeh 的使用方式分成四类:

运行模式典型入口适用场景关键特点
standalone HTMLoutput_file() / save() / show()分享单个交互图表生成独立 HTML,交互主要在浏览器端完成
Notebookoutput_notebook()教学、探索分析图表直接显示在 Notebook 单元格中
Bokeh Serverbokeh serve app.py --showPython 回调、实时更新、状态同步浏览器和 Python 进程持续通信
embed 到现有 Web 页面components()file_html()server_document()Flask、Django、已有前端页面适合把 Bokeh 接入更大的 Web 系统

初学阶段你最常用的是前两种:

  • standalone HTML
  • Notebook

它们的共同点是:
你写 Python 代码生成图表对象,Bokeh 再把这些对象转换成浏览器可以理解的内容,由 BokehJS 在前端渲染和交互。

Bokeh Server 的不同点在于:

  • 浏览器中的交互事件会继续传回 Python
  • Python 回调函数可以重新计算数据并推回前端
  • 因此它更适合筛选器、实时刷新、复杂业务逻辑

你现在可以先记住一个简单判断:

  • 只想生成交互图表文件 → 先用 standalone HTML
  • 在 Notebook 里学习和试验 → 用 Notebook
  • 需要 Python 回调或实时更新 → 用 Bokeh Server
  • 需要嵌入现有网站 → 学第八章的 embed 方式

这一点非常重要,因为它会直接影响后面章节中代码应该如何运行:

  • 第六章的 CustomJS 示例很多可以直接用于 standalone HTML
  • 第七章的 Python 回调示例必须通过 bokeh serve 运行
  • 第八章会系统讲解 standalone、Notebook、embed 等输出方式的差异

1.7 Bokeh 适合什么,不适合什么

Bokeh 不是要替代所有可视化工具。不同库有不同的优势。

需求场景推荐工具理由
论文配图、静态报告Matplotlib出版质量高,控制细节丰富
快速统计图表Seaborn默认样式美观,适合统计分析
交互式 Web 图表Bokeh原生浏览器交互,输出方式灵活
仪表板和数据应用Bokeh Server支持 Python 回调、状态同步和实时更新
快速探索性分析Plotly ExpressAPI 简洁,上手快

Bokeh 的主要优势包括:

  • 使用 Python 编写图表逻辑
  • 输出 HTML,便于分享和嵌入
  • 浏览器端由 BokehJS 渲染,交互体验自然
  • 与 NumPy、Pandas 等 Python 数据生态配合良好
  • 既能画单张图,也能扩展为完整的 Bokeh Server 应用
  • 支持多种输出方式,包括 HTML、Notebook、Web 组件和图片导出

如果你的目标是“一张精致的静态出版图”,Matplotlib 可能更合适;如果你的目标是“可以在浏览器中探索的数据图表”,Bokeh 就非常适合。

1.8 Bokeh 的三层接口

Bokeh 提供多个层次的接口。快速入门阶段不需要全部掌握,但你应该知道它们各自解决什么问题。

第一层:bokeh.plotting

这是最常用的高级绘图接口,适合大部分日常图表。

from bokeh.plotting import figure, show

p = figure(title="plotting 接口示例")
p.line([1, 2, 3], [4, 5, 6], line_width=2)
p.scatter([1, 2, 3], [4, 5, 6], size=8)

show(p)

你在本章前面使用的 figure()p.line()p.scatter() 都属于这一层。

第二层:bokeh.models

这一层提供更细粒度的模型对象,例如数据源、工具、坐标轴、范围、颜色映射、回调等。你通常会把它和 bokeh.plotting 一起使用。

from bokeh.models import ColumnDataSource, HoverTool
from bokeh.plotting import figure, show

source = ColumnDataSource(data={
    "x": [1, 2, 3],
    "y": [4, 5, 6],
    "label": ["A", "B", "C"],
})

p = figure(title="models 接口示例")
p.scatter("x", "y", source=source, size=12)

p.add_tools(HoverTool(tooltips=[
    ("标签", "@label"),
    ("x", "@x"),
    ("y", "@y"),
]))

show(p)

这类写法会在交互、联动和数据更新中频繁出现。

第三层:bokeh.iobokeh.embed 和相关输出接口

这一层主要控制图表如何输出、保存或嵌入。

from bokeh.embed import components
from bokeh.plotting import figure

p = figure(title="嵌入示例")
p.line([1, 2, 3], [4, 5, 6])

script, div = components(p)

components(p) 会返回一段 <script> 和一个 <div>,方便你把 Bokeh 图表嵌入到 Flask、Django 或其他 Web 页面中。

选择建议:

  • 日常画图:优先使用 bokeh.plotting
  • 需要悬停、筛选、联动、回调:结合使用 bokeh.models
  • 需要控制 HTML、Notebook、导出或嵌入:学习 bokeh.iobokeh.embed
  • 需要实时应用和服务端状态:学习 Bokeh Server

三层接口的更完整说明见第二章 2.4

1.9 本章小结

本章你已经完成了 Bokeh 的第一轮入门:

  • 知道 Bokeh 的核心定位是 Python 驱动的 Web 交互可视化
  • 安装并验证了 Bokeh 环境
  • figure() 创建了第一张交互式图表
  • 使用 output_file()show() 生成并打开 HTML 文件
  • 初步接触了 ColumnDataSourceHoverTool
  • 了解了 Bokeh 与 Matplotlib、Seaborn、Plotly 等工具的差异
  • 知道了 Bokeh 的常用接口层次

接下来建议阅读第二章:核心概念。理解 ColumnDataSourceFigureGlyphDocument 之后,你会更容易掌握后续的交互、布局和 Bokeh Server。

1.10 常见坑

坑 1:把 standalone HTML 和 Bokeh Server 混为一谈

这是初学者最常见的问题。

如果你写的是:

  • output_file() / save() / show()
  • output_notebook()

那么你通常得到的是 standalone 文档。这类图表可以有缩放、平移、悬停等浏览器端交互,但 Python 回调不会继续运行

如果你写的是:

  • curdoc()
  • on_change()
  • add_periodic_callback()

那么通常说明你已经进入 Bokeh Server 场景,需要使用 bokeh serve 运行。关于这一点,见第七章

坑 2:一开始就忽略 ColumnDataSource

简单示例里直接传列表没有问题,但只要你需要下面这些能力:

  • 悬停显示更多字段
  • 多个图共享数据
  • 做选择联动
  • 做数据更新

就应该尽早切换到 ColumnDataSource。它会在第二章详细展开。

坑 3:以为 show() 就等于“部署完成”

show() 更像是“快速预览”:

  • 在脚本里,通常会打开浏览器
  • 在 Notebook 里,通常会直接内联显示

但这不等于你已经掌握了分享、嵌入、导出、集成到 Web 框架中的方法。相关内容请继续看第八章

坑 4:还没区分输出方式,就急着查交互为什么不工作

如果你发现“图显示出来了,但某些回调没反应”,先不要急着怀疑 API。
先问自己两个问题:

  1. 我现在运行的是 standalone / Notebook,还是 Bokeh Server?
  2. 我使用的是前端交互(例如 HoverToolCustomJS),还是 Python 回调?

很多问题其实不是代码错了,而是运行方式和代码模型不匹配

下一步建议

建议按下面顺序继续:

  1. 阅读第二章:核心概念,重点理解 ColumnDataSource
  2. 阅读第八章:输出选项,建立更完整的运行模式认识
  3. 准备学习 Python 回调前,再阅读第七章:Bokeh Server 进阶