I have been struggling with trying to understand how to use widgets to filter Bokeh scatterplots. I'm new to both Bokeh and JavaScript so it has been a steep learning curve. I have tried a lot of code I've found online but have not found anything that works or does what I specifically need to do. I would greatly appreciate some help with my code - I'm sure the CustomJS is not doing what I need it to do.
I have adapted the code below from the Bokeh gallery to illustrate what I'd like to do. It is plotting up the iris dataset. I would like users to be able to select a species from the checkbox and the graph to update and only plot that subset of the data.
Thank you!
from bokeh.plotting import figure, output_notebook, show
from bokeh.sampledata.iris import flowers
from bokeh.models import BooleanFilter, CDSView, ColumnDataSource
from bokeh.models.widgets import CheckboxGroup
from bokeh.models.callbacks import CustomJS
output_notebook()
alldata = ColumnDataSource(flowers)
subdata = ColumnDataSource(flowers)
checkbox = CheckboxGroup(labels = flowers['species'].unique().tolist())
p = figure()
p.circle('petal_length', 'petal_width', source = subdata)
show(p)
show(checkbox)
callback = CustomJS(args=dict(subdata=subdata, alldata=alldata),
code="""
const spec = cb_obj.value;
subdata = alldata[spec];
subdata.data.change.emit();
""")
checkbox.js_on_change('value', callback)
I've tried another approach using CDS views / filtering but with no success.
from bokeh.plotting import figure, output_notebook, show
from bokeh.sampledata.iris import flowers
from bokeh.models import BooleanFilter, CDSView, ColumnDataSource, IndexFilter, GroupFilter
from bokeh.models.widgets import CheckboxGroup
from bokeh.models.callbacks import CustomJS
output_notebook()
alldata = ColumnDataSource(flowers)
checkbox = CheckboxGroup(labels = flowers['species'].unique().tolist())
show(checkbox)
filter = IndexFilter(indices=list(range(0,len(flowers['species']))))
checkbox.js_on_change('value', callback)
callback = CustomJS(args=dict(src=alldata, filter=filter), code='''
const indices = []
for (var i = 0; i < src.get_length(); i++) {
console.log(i, src.data['species'][i], cb_obj.value)
if (src.data['species'][i] == cb_obj.value) {
indices.push(i)
}
}
filter.indices = indices
src.change.emit()
''')
view = CDSView(source=alldata, filters=[filter])
p = figure()
p.circle('petal_length', 'petal_width', source = alldata, view = view)
show(p)