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

Bokeh双数据源双图场景下TapTool跨图回调实现问题咨询

Bokeh TapTool跨图回调实现方案

你提供的原始代码核心问题有两个:

  1. 传入CustomJS的lines_y是ColumnDataSource对象,它的data属性是键值对结构,你直接按数组索引取值会拿到空值
  2. 没有把所有待切换的y值序列整理成JS可以直接按索引匹配的结构,回调时无法快速拿到选中元素对应的数据

修正后可直接运行的代码

from bokeh.layouts import row
from bokeh.models import ColumnDataSource, CustomJS, TapTool
from bokeh.plotting import figure, show
import numpy as np

# 第一个图的数据源:如果是7个圆形改对应字段即可
source_bars = ColumnDataSource({'x': [1, 2, 3], 'y': [2, 4, 1] , 'colnames': ['A', 'B', 'C']})
# 提前准备所有待切换的第二图数据,索引和第一图元素一一对应:第n个元素对应点第一图第n个元素展示的数据
lines_y = [np.random.random(3).tolist() for i in range(3)]

# 第二图初始数据源
src1 = ColumnDataSource(data=dict(x= [1, 2, 3], y=lines_y[0]))

plot1 = figure(tools = 'tap')
# 如果是圆形换成circle方法即可,逻辑完全一致
bars = plot1.vbar(x = 'x', top = 'y', source = source_bars, bottom = 0, width = 0.5)

plot2 = figure()
lines = plot2.vbar(x = 'x', top = 'y', source = src1, bottom = 0, width = 0.5)

# JS回调逻辑
code = '''
if (cb_data.source.selected.indices.length > 0){
    // 取第一个选中元素的索引
    const selected_idx = cb_data.source.selected.indices[0];
    // 匹配对应的数据更新第二图数据源
    src1.data['y'] = lines_y[selected_idx];
    src1.change.emit();
}
'''

# 把回调要用到的对象都传入args
plot1.select(TapTool).callback = CustomJS(args={'src1': src1, 'lines_y': lines_y}, code=code)

show(row(plot1, plot2))

通用实现思路

  • 提前整理好第一图元素和第二图待展示数据的映射关系,推荐用数组按索引对应,JS取值最方便
  • CustomJS的args参数要主动传入所有回调会用到的对象,JS无法直接读取Python侧定义的变量
  • 回调更新数据源后必须调用change.emit()触发Bokeh重绘,修改才会生效

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 21:54:00