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

Bokeh共享图例双图表:click_policy点击隐藏功能失效求助

实现Bokeh双图表共享可点击隐藏的图例

要实现单个图例控制两个图表的显示/隐藏,核心是让所有需要联动的渲染器(Renderer)归属到同一个图例所在的图表中,同时隐藏该图表的其他视觉元素,只保留图例。以下是修正后的完整代码:

from bokeh.plotting import figure, row, gridplot
from bokeh.models import ColumnDataSource, Legend, LegendItem, CDSView, IndexFilter
import pandas as pd
import numpy as np

# 模拟测试数据(可替换为你的实际DataFrame)
np.random.seed(42)
dates = pd.date_range(start='2023-01-01', periods=100)
data = pd.DataFrame({
    'timestamp': dates,
    'col1': np.random.randn(100).cumsum(),
    'col2': np.random.randn(100).cumsum(),
    'col3': np.random.randn(100).cumsum()
})
CUSTOM = ['#ff0000', '#00ff00', '#0000ff']

# 主数据源
source = ColumnDataSource(data)

# 创建两个主图表
p1 = figure(x_axis_type='datetime', title='时序图', height=430, width=900, y_minor_ticks=5)
hist = figure(title='分布直方图', x_axis_label='数值', y_axis_label='频次', height=430, width=200)

# 存储所有渲染器和图例项
renderers = []
legend_items = []

# 为每一列添加对应的两个图表元素
for i, col in enumerate(data.columns[1:]):
    # 时序图的circle
    circle = p1.circle(x='timestamp', y=col, size=3, color=CUSTOM[i], alpha=0.8, source=source)
    # 直方图的quad:基于当前列的分布数据构建
    counts, bins = np.histogram(data[col], bins=10)
    hist_source = ColumnDataSource({
        'top': counts,
        'bottom': [0]*len(counts),
        'left': bins[:-1],
        'right': bins[1:]
    })
    quad = hist.quad(top='top', bottom='bottom', left='left', right='right',
                     source=hist_source, color=CUSTOM[i], alpha=0.8)
    
    # 将同一列的两个渲染器关联到同一个图例项
    legend_items.append(LegendItem(label=col, renderers=[circle, quad]))
    # 收集所有渲染器
    renderers.extend([circle, quad])

# 创建隐藏的dummy图表,仅用于承载图例
dum_fig = figure(width=0, height=0, outline_line_alpha=0, toolbar_location=None)
# 隐藏所有不需要的元素
for elem in dum_fig.grid + dum_fig.axis:
    elem.visible = False
# 将所有渲染器添加到dummy图中
dum_fig.renderers += renderers
# 添加图例并设置点击策略
legend = Legend(items=legend_items, location='bottom_center', orientation='horizontal', ncols=3)
legend.click_policy = 'hide'
dum_fig.add_layout(legend, 'below')

# 组合图表:主图表横向排列,下方放置共享图例
main_row = row(p1, hist)
final_layout = gridplot([[main_row], [dum_fig]], toolbar_location=None)

# 显示图表(Jupyter环境中执行)
# from bokeh.io import show
# show(final_layout)

关键修正点说明:

  1. 渲染器关联逻辑:在循环中为每一列的两个渲染器(时序图的circle、直方图的quad)创建对应的LegendItem,确保图例项与两个图表的元素一一绑定。
  2. Dummy图表优化:将dummy图的宽高设为0,彻底隐藏图表本体,仅保留下方的图例;同时将所有需要联动的渲染器添加到该图中,这样图例的点击操作会同步控制两个主图的对应元素。
  3. 数据源适配:修复了原代码中直方图数据源为空的问题,根据每列数据动态生成直方图的统计数据,保证图表能正常显示。
  4. 布局调整:用gridplot将主图表行和图例行垂直排列,保证图例在两个主图的下方,布局更合理。

内容的提问来源于stack exchange,提问作者Sara.SP92

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 02:52:29