Hardian Lawi
Hardian Lawi

Reputation: 608

Bokeh Widget Slicing data

I am trying to create a plot using bokeh to visualize my data on IPython Notebook. I want to add some widgets to make it more interactive. Below is an example of the codes.

from bokeh.models import CustomJS, ColumnDataSource
from bokeh.plotting import Figure, output_notebook, show
from bokeh.models.widgets import Select
from bokeh.layouts import column

output_notebook()

x = [x*0.005 for x in range(0, 200)]
y = x
z = ['A' if i>50 else 'B' for i in range(len(x))]

source = ColumnDataSource(data=dict(x=x, y=y, z=z))

plot = Figure(plot_width=400, plot_height=400)
plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)

def callback(source=source):
    data=source.get('data')
    f = cb_obj.get('value')
    x, y, z = data['x'], data['y'], data['z']
    x = [x[i] for i in range(len(x)) if z[i] == f]
    y = [y[i] for i in range(len(y)) if z[i] == f]
    z = [z[i] for i in range(len(z)) if z[i] == f]
    source.trigger('change')

slides = Select(title="Option:", value = 'A', options=['A', 'B'], 
                callback=CustomJS.from_py_func(callback))

layout = column(slider,plot)

show(layout)

enter image description here

I want to make it such that if I choose other option, the plot will change accordingly based on the criteria I specify in the callback function. Any suggestion on why the codes do not work?

P.S. I used the codes from here, but I change the widgets because the problem I am facing is similar to the above http://docs.bokeh.org/en/0.11.1/docs/user_guide/interaction.html#customjs-with-a-python-function

Upvotes: 0

Views: 867

Answers (1)

Anthonydouc
Anthonydouc

Reputation: 3364

The issue is you are not actually changing the contents of data['x'], data['y'] or data['z'].

Second issue is, if you change the source data, then you cant change it back as it no longer contains the full data you begun with. Work around is passing in the original data to the callback, and assigning the filtered data to the ColumnDataSource, without changing the original data.

from bokeh.models import CustomJS, ColumnDataSource
from bokeh.plotting import Figure, output_notebook, show
from bokeh.models.widgets import Select
from bokeh.layouts import column

output_notebook()

x = [x*0.005 for x in range(0, 200)]
y = x
z = ['A' if i>50 else 'B' for i in range(len(x))]

original_source = ColumnDataSource(data=dict(x=x, y=y, z=z))
source = ColumnDataSource(data=dict(x=x, y=y, z=z))

plot = Figure(plot_width=400, plot_height=400)
plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)

def callback(source=source, original_source = original_source):
    data=original_source.data
    s_data = source.data
    f = cb_obj.value
    x, y, z = data['x'], data['y'], data['z']
    x = [x[i] for i in range(len(x)) if z[i] == f]
    y = [y[i] for i in range(len(y)) if z[i] == f]
    z = [z[i] for i in range(len(z)) if z[i] == f]
    s_data['x'] = x
    s_data['y'] = y
    s_data['z'] = z
    source.trigger('change')

slides = Select(title="Option:", value = 'A', options=['A', 'B'], 
                callback=CustomJS.from_py_func(callback))

layout = column(slides,plot)

show(layout)

Upvotes: 1

Related Questions