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

Bokeh仪表板Slider控件实现DataTable响应式过滤失效问题求助

Bokeh滑块过滤DataTable失效问题修复方案

核心错误点

  • 变量名不匹配:CustomJS的args参数中传入的表格变量名为table,但回调代码中使用的是data_table,JS环境无法识别目标表格对象
  • 缺少原始数据传入:回调代码中使用的groupeddf、sensor_2都属于Python端变量,没有传入JS执行环境,无法直接读取
  • 语法不兼容:CustomJS运行在浏览器端的JavaScript环境,不支持Pandas DataFrame的过滤语法,需要按JS逻辑实现数据过滤
  • 无全量数据副本:直接修改表格绑定的ColumnDataSource会丢失原始全量数据,后续调整滑块阈值时无法恢复被过滤的数据,需要单独存储全量原始数据用于每次过滤

修正后完整代码

from operator import index
from bokeh.models.widgets.markups import Div
import numpy as np
from numpy.lib import source
import pandas as pd
from bokeh.io import curdoc,show
from bokeh.layouts import column, row, gridplot,widgetbox
from bokeh.models import ColumnDataSource, CustomJS,Select, Slider, BoxSelectTool, LassoSelectTool, Tabs, Panel, LinearColorMapper, ColorBar, BasicTicker, PrintfTickFormatter, MultiSelect, DataTable, TableColumn
from bokeh.plotting import figure, curdoc
from bokeh.palettes import viridis, gray, cividis, Category20, Category20c
from bokeh.transform import factor_cmap,cumsum
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import classification_report, confusion_matrix, mean_squared_error, r2_score, recall_score, f1_score
from sklearn.preprocessing import StandardScaler, PolynomialFeatures
from sklearn.cluster import KMeans
from sklearn.svm import SVC
from sklearn.decomposition import PCA
from math import pi
from bokeh.transform import cumsum

np.random.seed(42)

#define the categorical variable
category_a = ['A','B','C']
category_b = ['X','Y','Z']
df_random = pd.DataFrame({
   'id': np.arange(0, 100),
   'date': pd.date_range(start='1/1/2021', periods=100, freq='D').astype(str), # 日期转字符串避免JS序列化问题
   'month':np.random.randint(1, 12, 100),
   'sensor_1': np.random.uniform(0, 1,100),
   'sensor_2': np.random.uniform(10, 150, 100),
   'sensor_3': np.random.randint(0, 90, 100),
   'sensor_4': np.random.randint(0, 450, 100),
   'sensor_5': np.random.randint(0, 352, 100),
   'categorya': np.random.choice(category_a, 100, p=[0.2, 0.4, 0.4]),
   'categoryb': np.random.choice(category_b, 100, p=[0.6, 0.2, 0.2]),
})


source = ColumnDataSource(data=df_random)

columns = [
    TableColumn(field='id', title='ID'),
    TableColumn(field='date', title='Date'),
    TableColumn(field='month', title='Month'),
    TableColumn(field='sensor_1', title='Sensor 1'),
    TableColumn(field='sensor_2', title='Sensor 2'),
    TableColumn(field='sensor_3', title='Sensor 3'),
    TableColumn(field='sensor_4', title='Sensor 4'),
    TableColumn(field='sensor_5', title='Sensor 5'),
    TableColumn(field='categorya', title='Category A'),
    TableColumn(field='categoryb', title='Category B'),
]

data_table = DataTable(source=source, columns=columns, width=1100, height=280)
slider = Slider(start = 1, end = 150, value = 10, step = 1, title = "sensor_2最小阈值", width = 300) # 阈值范围调整为和sensor_2匹配

callback_code = """ 
const threshold = slider.value;
const original = original_data;
const new_data = {};
// 初始化所有列的空数组
Object.keys(original).forEach(col => {
  new_data[col] = [];
});
// 逐行过滤符合条件的数据
for (let i = 0; i < original.sensor_2.length; i++) {
  if (original.sensor_2[i] >= threshold) {
    Object.keys(original).forEach(col => {
      new_data[col].push(original[col][i]);
    });
  }
}
table.source.data = new_data;
"""

# 传入全量原始数据、滑块、表格三个对象
callback = CustomJS(args = dict(slider = slider, table = data_table, original_data=df_random.to_dict('list')), code = callback_code)
slider.js_on_change('value', callback)

layouttable=column(slider, data_table) # widgetbox已弃用,替换为column兼容性更好

curdoc().title = "table"
curdoc().add_root(layouttable)

多滑块扩展说明

后续新增滑块实现多维度过滤只需两步:

  1. 定义新滑块实例后,将其加入CustomJS的args字典中
  2. 在回调代码的过滤判断逻辑中,新增对应列的阈值判断条件即可,所有过滤都基于全量原始数据副本,不会出现数据丢失问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 07:36:05