Reputation: 378
I am trying to use a slider widget in Bokeh to reactively filter a DataTable and I think I am missing something in my code. The table is not updating as I move the slider. Here is my code:-
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)
Ideally, I would like to be able to add in more slider widgets to help me filter the data table to a granular level. But for now I would like to be able to get it working at a simple level. Can anyone point out what I am doing wrong?
Upvotes: 0
Views: 685
Reputation: 725
first widgetbox not supported anymore. you should use row, column etc.
first : slider.on_change('value', update)
create a function that 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
we cannot change only sensor_2 like source.data['sensor_2]
because it change only one value and lens of source would be different.
full code
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)
Upvotes: 1