What are you trying to do?
I want to plot a dataset and filter it using a slider based on the date retrieved from a dataframe.
What have you tried that did NOT work as expected?
The graph is only updated correctly the first time. On the second, third, or subsequent updates, it fails to update, and it shows everything as blank
I’m using Bokeh 2.4.3.
df = pd.DataFrame({
'x': [17, 26, 22, 23, 18],'y': [39, 34, 16, 45, 4],
'Date': pd.to_datetime(['04-12-2022', '02-12-2022', '05-12-2022', '05-12-2022', '06-12-2022'], format='%d-%m-%Y'),
'Title': ['Title 1', 'Title 2', 'Title 3', 'Title 4', 'Title 5'],
'topic_prediction': [3, 4, 0, 4, 2]
})
source = ColumnDataSource(data=dict(
x=df['x'], y=df['y'],
desc=df['topic_prediction'],
titles=df['Title'],
date=df['Date']
))
hover = HoverTool(tooltips=[
("Title", "@titles"),
("Date", "@date{%d-%m-%Y}")
], formatters={'@date': 'datetime'})
plot = figure(plot_width=300, plot_height=300, tools=[hover])
scatter = plot.scatter('x', 'y', size=5, source=source)
def date_sidebar(source=source, scatter=scatter):
callback = CustomJS(args=dict(source=source, scatter=scatter), code="""
const selected_date = new Date(cb_obj.value);
const data = source.data;
const x = data['x'];
const y = data['y'];
const desc = data['desc'];
const titles = data['titles'];
const dates = data['date'];
const filtered_x = [];
const filtered_y = [];
const filtered_desc = [];
const filtered_titles = [];
const filtered_dates = [];
for (let i = 0; i < dates.length; i++) {
const date = new Date(dates[i]);
if (date.toDateString() === selected_date.toDateString()) {
filtered_x.push(x[i]);
filtered_y.push(y[i]);
filtered_desc.push(desc[i]);
filtered_titles.push(titles[i]);
filtered_dates.push(dates[i]);
}
}
scatter.data_source.data = {
x: filtered_x,
y: filtered_y,
desc: filtered_desc,
titles: filtered_titles,
date: filtered_dates
};
scatter.data_source.change.emit();
""")
return callback
slider_callback = date_sidebar()
date_slider = DateSlider(title='Select Date', start=df['Date'].min(), end=df['Date'].max(), value=df['Date'].min())
date_slider.js_on_change('value', slider_callback)
layout = column(date_slider, plot)
show(layout)