You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Bokeh堆叠面积图添加HoverTool提示框?

给Bokeh堆叠面积图添加HoverTool提示框的解决方案

这个问题确实挺常见的——Bokeh的varea_stack虽然能快速生成堆叠面积图,但默认情况下没法直接给堆叠区域加HoverTool,因为它内部是基于原始数据计算堆叠位置的,我们需要的每个区域的上下边界值并没有直接存放在数据源里。不过有个直观的解决办法:预先计算好每一层堆叠的顶部和底部y值,然后用这些数据绘制面积图并配置HoverTool。

下面是修改后的完整代码,带详细注释:

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

# 原始数据
data = {
    "months": [date(2019, 5, 1), date(2019, 6, 1), date(2019, 7, 1), date(2019, 8, 1)],
    "dogs": [7, 5, 12, 8],
    "cats": [25, 20, 10, 7],
}

# 计算每一层堆叠的上下边界值
# Dogs层:底部是0,顶部就是自身的数值
data["dogs_bottom"] = [0] * len(data["dogs"])
data["dogs_top"] = data["dogs"]
# Cats层:底部是Dogs层的顶部,顶部是Dogs+Cats的总和
data["cats_bottom"] = data["dogs"]
data["cats_top"] = [d + c for d, c in zip(data["dogs"], data["cats"])]

# 创建包含堆叠边界的数据源
source = ColumnDataSource(data=data)

# 初始化绘图对象
p = figure(
    min_width=500,
    plot_height=300,
    sizing_mode="stretch_width",
    toolbar_location=None,
    x_axis_type="datetime",
)

# 先绘制底层的Cats面积(堆叠图要从下往上画)
p.varea(
    x="months",
    y1="cats_bottom",
    y2="cats_top",
    color="#00ff00",
    source=source,
    name="cats",  # 给这个渲染器命名,方便HoverTool识别
    legend_label="Cats"
)

# 再绘制上层的Dogs面积
p.varea(
    x="months",
    y1="dogs_bottom",
    y2="dogs_top",
    color="#ff0000",
    source=source,
    name="dogs",  # 命名对应数据源的字段
    legend_label="Dogs"
)

# 配置HoverTool
hover = HoverTool(
    tooltips=[
        ("日期", "@months{%F}"),
        ("类别", "$name"),
        ("当前类别数量", "@$name"),
        ("累计总数量", "@$name_top"),
    ],
    formatters={
        "@months": "datetime",  # 格式化日期显示
    },
    renderers=p.renderers,  # 对所有面积渲染器生效
    mode="vline"  # 垂直悬停线,方便对齐日期点
)

# 添加HoverTool到图中
p.add_tools(hover)
# 可选:点击图例可以隐藏对应层
p.legend.click_policy = "hide"

show(p)

关键说明:

  1. 堆叠边界计算:每一层的底部是上一层的顶部,顶部是自身数值加上上一层的顶部(最底层底部为0),这样每个面积区域的范围就明确了。
  2. 渲染器命名:给每个varea设置name参数,对应数据源里的字段名,HoverTool可以通过$name自动匹配当前悬停的区域,动态获取对应的数值。
  3. HoverTool配置:用@$name和@$name_top可以动态调用对应层的原始数值和堆叠后的顶部数值,mode="vline"让悬停时显示垂直辅助线,更方便对应到x轴的日期点。

如果有更多堆叠层,只需要按照这个逻辑依次计算每一层的bottom和top字段即可,扩展性很强。

内容的提问来源于stack exchange,提问作者Phil Gyford

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:04:47