Skip to content

Instantly share code, notes, and snippets.

@dennisobrien
Last active February 23, 2026 00:55
Show Gist options
  • Select an option

  • Save dennisobrien/450d7da20daaba6d39d0 to your computer and use it in GitHub Desktop.

Select an option

Save dennisobrien/450d7da20daaba6d39d0 to your computer and use it in GitHub Desktop.
Filter a Bokeh DataTable using multiple filter widgets. Runs in a Jupyter notebook.
import bokeh.embed
import bokeh.io
import bokeh.models
import bokeh.models.widgets
import bokeh.plotting
import pandas as pd
from pandas_datareader import wb
bokeh.plotting.output_notebook()
df = wb.download(indicator='NY.GDP.PCAP.KD', country=['US', 'CA', 'MX'], start=2005, end=2008)
df = df.reset_index()
source = bokeh.models.ColumnDataSource(df)
original_source = bokeh.models.ColumnDataSource(df)
columns = [
bokeh.models.widgets.TableColumn(field="country", title="Country"),
bokeh.models.widgets.TableColumn(field="year", title="Year"),
bokeh.models.widgets.TableColumn(field="NY.GDP.PCAP.KD", title="NY.GDP.PCAP.KD"),
]
data_table = bokeh.models.widgets.DataTable(source=source, columns=columns)
# callback code to be used by all the filter widgets
# requires (source, original_source, country_select_obj, year_select_obj, target_object)
combined_callback_code = """
var data = source.get('data');
var original_data = original_source.get('data');
var country = country_select_obj.get('value');
console.log("country: " + country);
var year = year_select_obj.get('value');
console.log("year: " + year);
for (var key in original_data) {
data[key] = [];
for (var i = 0; i < original_data['country'].length; ++i) {
if ((country === "ALL" || original_data['country'][i] === country) &&
(year === "ALL" || original_data['year'][i] === year)) {
data[key].push(original_data[key][i]);
}
}
}
target_obj.trigger('change');
source.trigger('change');
"""
# define the filter widgets, without callbacks for now
country_list = ['ALL'] + df['country'].unique().tolist()
country_select = bokeh.models.widgets.Select(title="Country:", value=country_list[0], options=country_list)
year_list = ['ALL'] + df['year'].unique().tolist()
year_select = bokeh.models.widgets.Select(title="Year:", value=year_list[0], options=year_list)
# now define the callback objects now that the filter widgets exist
generic_callback = bokeh.models.CustomJS(
args=dict(source=source,
original_source=original_source,
country_select_obj=country_select,
year_select_obj=year_select,
target_obj=data_table),
code=combined_callback_code
)
# finally, connect the callbacks to the filter widgets
country_select.callback = generic_callback
year_select.callback = generic_callback
p = bokeh.io.vplot(country_select, year_select, data_table)
bokeh.plotting.show(p)
@nepakumar
Copy link

Faced same issue, filtering doesnt work. It creates the HTML file, though

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment