Bokeh仪表板中的DataTable;使用滑块小部件进行反应式过滤

DataTable in Bokeh dashboard; reactive filtering with a slider widget

我正在尝试使用 Bokeh 中的滑块小部件来反应性地过滤 DataTable,我想我的代码中遗漏了一些东西。 table 在我移动滑块时没有更新。这是我的代码:-

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)


print("step 1")
#define the categorical variable
category_a = ['A','B','C']
category_b = ['X','Y','Z']
print("step 2")
df_random = pd.DataFrame({
   'id': np.arange(0, 100),
   'date': pd.date_range(start='1/1/2021', periods=100, freq='D'),
   '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 = 100, value = 10, step = 1, title = "i", width = 300)

callback_code = """ i = slider.value;
                    new_data = groupeddf[sensor_2>=slider.value]
                    data_table.source.data = new_data """



callback = CustomJS(args = dict(slider = slider, table = data_table), code = callback_code)
slider.js_on_change('value', callback)


layouttable=widgetbox(slider, data_table)

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

理想情况下,我希望能够添加更多滑块小部件,以帮助我将数据 table 过滤到更精细的级别。但现在我希望能够让它在一个简单的层面上工作。 谁能指出我做错了什么?

不再支持第一个小部件框。你应该使用行、列等

首先:slider.on_change('value', update)

创建一个更新函数

def update(attr, old, new):
    upd_slider = df_random[df_random['sensor_2'] > slider.value]
    updated_data ={
        'id': upd_slider['id'],
        'date': upd_slider['date'],
        'month': upd_slider['month'],
        'sensor_1': upd_slider['sensor_1'],
        'sensor_2': upd_slider['sensor_2'],
        'sensor_3': upd_slider['sensor_3'],
        'sensor_4': upd_slider['sensor_4'],
        'sensor_5': upd_slider['sensor_5'],
        'categorya': upd_slider['categorya'],
        'categoryb': upd_slider['categoryb'],
    }
    source.data = updated_data

我们不能像source.data['sensor_2]那样只改变sensor_2,因为它只改变一个值,源镜头会不同。

完整代码

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,Column
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)


print("step 1")
#define the categorical variable
category_a = ['A','B','C']
category_b = ['X','Y','Z']
print("step 2")
df_random = pd.DataFrame({
   'id': np.arange(0, 100),
   'date': pd.date_range(start='1/1/2021', periods=100, freq='D'),
   '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'),
]
def update(attr, old, new):
    upd_slider = df_random[df_random['sensor_2'] > slider.value]
    updated_data ={
        'id': upd_slider['id'],
        'date': upd_slider['date'],
        'month': upd_slider['month'],
        'sensor_1': upd_slider['sensor_1'],
        'sensor_2': upd_slider['sensor_2'],
        'sensor_3': upd_slider['sensor_3'],
        'sensor_4': upd_slider['sensor_4'],
        'sensor_5': upd_slider['sensor_5'],
        'categorya': upd_slider['categorya'],
        'categoryb': upd_slider['categoryb'],
    }
    source.data = updated_data


data_table = DataTable(source=source, columns=columns, width=1100, height=280)

slider = Slider(start = 1, end = 100, value = 10, step = 1, title = "i", width = 300)
slider.on_change('value', update)





layouttable=Column(slider, data_table)

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