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

Bokeh交互需求:点击绘图点生成对应多值独立数据表

解决Bokeh中图表点击动态生成对应数据表的问题

问题背景

我有两个键值匹配的数据源:

  • Source 1:存储带唯一键的键值对,用于绘制图表
  • Source 2:键与Source 1完全一致,但每个键对应多条数据记录

需求目标

实现以下交互功能:

  • 点击图表上的点时,弹出独立数据表,展示Source 2中对应键的所有行
  • 选中多个点时,同时显示对应数量的独立数据表
  • 取消选中点时,对应的数据表自动隐藏

当前遇到的问题

已实现图表与数据表的基础联动(点击点时对应行高亮),但无法完成两个核心需求:

  1. 无法让数据表仅显示单个键对应的所有数据(尝试替换source2.selected.indices为source2.indices无效果)
  2. 找不到动态显示/隐藏数据表的实现方法

解决方案代码

以下是修改后的完整代码,实现动态创建/销毁数据表,以及精准过滤对应键的数据:

import numpy as np
import pandas as pd
from bokeh.models.callbacks import CustomJS
from bokeh.plotting import figure
from bokeh.io import show
from bokeh.layouts import column, row, Spacer
from bokeh.models.widgets import DataTable, TableColumn
from bokeh.models import ColumnDataSource, TapTool, Div

# 初始化数据源
source = ColumnDataSource(pd.DataFrame(
    np.array([[i, i] for i in range(0, 10)]), columns=['x', 'y']))

data = [[i, f"data.{i}"] for i in range(0, 10)]
data.extend([[i, f"data.{i}_extra"] for i in range(0, 10)])
source2 = ColumnDataSource(pd.DataFrame(data, columns=['x', 'data']))

# 创建图表
plot = figure(title="点击点查看对应数据", tools="tap,pan,box_zoom,wheel_zoom,save,reset", width=400)
plot.circle('x', 'y', source=source, line_color=None, color='red', size=10, selection_color='blue')

# 用于存放动态生成的数据表容器
table_container = column(spacing=10)

# 自定义JS回调:处理选中事件,动态创建/删除数据表
selection_callback = CustomJS(args=dict(source=source, source2=source2, container=table_container), code="""
    // 先清除已有的数据表,根据选中状态重新生成
    while (container.children.length > 0) {
        container.children.pop();
    }

    // 获取当前选中的所有点的x值
    const selectedXs = source.selected.indices.map(idx => source.data.x[idx]);
    
    // 为每个选中的x值创建对应的数据表
    selectedXs.forEach(xVal => {
        // 过滤source2中对应x值的数据
        const filteredData = {
            x: [],
            data: []
        };
        source2.data.x.forEach((x, idx) => {
            if (x === xVal) {
                filteredData.x.push(x);
                filteredData.data.push(source2.data.data[idx]);
            }
        });
        
        // 创建临时数据源
        const tempSource = new Bokeh.ColumnDataSource(filteredData);
        
        // 创建数据表列
        const columns = [
            new Bokeh.TableColumn({field: 'x', title: `键值: ${xVal}`}),
            new Bokeh.TableColumn({field: 'data', title: '数据内容'})
        ];
        
        // 创建数据表
        const table = new Bokeh.DataTable({
            source: tempSource,
            columns: columns,
            width: 500,
            height: 200,
            header_row_height: 30
        });
        
        // 添加到容器
        container.children.push(table);
        container.children.push(new Bokeh.Spacer(height=10));
    });
    
    // 触发容器更新
    container.change.emit();
""")

# 绑定点击工具和选中事件回调
plot.select(TapTool).callback = selection_callback
source.selected.js_on_change('indices', selection_callback)

# 布局展示
show(row(plot, column(Div(text="<h3>数据表展示区</h3>"), table_container), spacing=20))

代码关键说明

  1. 动态数据表管理:通过JS回调实时清空容器并重新创建对应选中点的数据表,确保选中状态与数据表数量完全匹配
  2. 精准数据过滤:针对每个选中的键值,从Source 2中过滤出对应的数据,创建临时数据源绑定到新数据表,保证每个表只展示对应键的内容
  3. 全场景交互支持:同时绑定TapTool和数据源的indices变化事件,点击单个点或框选多个点都能触发正确的更新逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 08:15:28