Skip to content Skip to sidebar Skip to footer

Interactively Change A Point Plot In Bokeh Using Rangeslider To Select Columns In A Pandas Dataframe

I have a pandas dataframe df where the first two columns represent x, y coordinates and the remaining columns represent time slices (t0,...tn) where the presence(1) or absence(0) o

Solution 1:

There are a number of issues in the code above:

  • It is cb_obj not cb.obj
  • Use modern js_on_change, not very old ad-hoc callback parameters
  • You are assigning to a local variabledata and then throwing away the result— need to literally assign to source.data at some point for there to be any effect.
  • To do this by updating data sources you would need two data sources, on that always has the complete data that you pull from, and another that you only use to hold the subset. If you only have one data source and you subset it, you've now thrown away data you can never get back. (Future subsets will be against the current subset, not the whole)
  • So, better to use CDSView for this, which lets you express an update-able subset view to apply to a constant data source.
  • JS does not have Pandas-like operations, you just have to do all the nested looping to check every row to determine the subset indices
  • Just guessing, but you will probably want to fix x/y ranges if you intend to maintain the same spatial extent for comparison, as the slider moves.

Here is a simplified working example:

from bokeh.layouts import column
from bokeh.plotting import figure, show
from bokeh.models import CustomJS, ColumnDataSource, RangeSlider, CDSView, IndexFilter

source = ColumnDataSource(data=dict(
    x=[1,2,3,4],
    y=[1,1,1,1],
    t0=[1,1,0,0],
    t1=[0,1,0,0],
    t2=[0,1,1,0],
    t3=[0,0,1,1],
    t4=[0,0,0,1],
    t5=[0,0,0,0],
))

p = figure(plot_height=500, x_range=(0,5), y_range=(0,2))

view = CDSView(source=source, filters=[IndexFilter([0, 1])])
p.circle('x', 'y', size=10, color="navy", alpha=0.8,
         source=source, view=view)

callback = CustomJS(args=dict(source=source, view=view), code="""
    const start = cb_obj.value[0]
    const end = cb_obj.value[1]
    const indices = []
    for (var i=0; i < source.get_length(); i++) {
        for (var j=start; j<=end; j++) {
            if (source.data["t" + j][i]==1) {
                indices.push(i)
                break
            }
        }
    }
    view.indices = indices
""")

ti_slider = RangeSlider(start=0, end=5, value=(0,1), step=1, title="Time Period")
ti_slider.js_on_change('value', callback)

show(column(ti_slider, p))

enter image description here

Post a Comment for "Interactively Change A Point Plot In Bokeh Using Rangeslider To Select Columns In A Pandas Dataframe"