How to link a multiselect widget to a datatable using bokeh in a jupyter notebook?

最后都变了- 提交于 2019-12-24 07:13:20

问题


I'm attempting to connect a datatable with a multiselect widget in bokeh. I've searched around and gathered that I need to develop a function to update the data source for the data table, but I seem to have two problems.

  1. I cannot seem to access the value of the multiselect object after I click it.
  2. I cannot seem to push the change to the notebook after receiving the change.

Here's an example of my code:

import pandas as pd
from bokeh.io import push_notebook
from bokeh.plotting import show, output_notebook
from bokeh.layouts import row
from bokeh.models.widgets import MultiSelect, DataTable, TableColumn
from bokeh.models import ColumnDataSource

output_notebook()

df=pd.DataFrame({'year':[2000,2001,2000,2001,2000,2001,2000,2001],
              'color':['red','blue','green','red','blue','green','red','blue'],
              'value':[ 0,1,2,3,4,5,6,7]})

columns=[TableColumn(field=x, title=x) for x in df.columns]
source=ColumnDataSource(df)
data_table=DataTable(source=source,columns=columns)

years=[2000,2001,2000,2001,2000,2001,2000,2001]

## MultiSelect won't let me store an integer value, so I convert them to strings

multi=MultiSelect(title="Select a Year", value=['2000','2001'],options=[str(y) for y in set(years)])

def update(attr,old, new):
    yr=multi.value
    yr_vals=[int(y) for y in yr]
    new_data=df[df.year.isin(yr_vals)]
    source.data=new_data
    push_notebook(handle=t)

multi.on_change('value',update)
t=show(row(multi,data_table),notebook_handle=True)

回答1:


push_notebook is uni-directional. That is, you can only push changes from the IPython kernel, to the JavaScript front end. No changes from the UI are propagated back to the running Python kernel. In other words, on_change is not useful (without more work, see below) If you want that kind of interaction, there are a few options:

  • Use ipywidgets with push_notebook. Typically this involved the interact function to automatically generate a simple UI with callbacks that use push_notebook to update the plots, etc. based on the widget values. Just to be clear, this approach uses ipywidgets, which are not Bokeh built-in widgets. You can see a full example notebook here:

    https://github.com/bokeh/bokeh/blob/master/examples/howto/notebook_comms/Jupyter%20Interactors.ipynb

  • Embed a Bokeh server application. The Bokeh server is what makes it possible for on_change callbacks on Bokeh widgets to function. Typically this involves making a function that defines the app (by specifying how a new document is created):

    def modify_doc(doc):
        df = sea_surface_temperature.copy()
        source = ColumnDataSource(data=df)
    
        plot = figure(x_axis_type='datetime', y_range=(0, 25))
        plot.line('time', 'temperature', source=source)
    
        def callback(attr, old, new):
            if new == 0:
                data = df
            else:
                data = df.rolling('{0}D'.format(new)).mean()
            source.data = ColumnDataSource(data=data).data
    
        slider = Slider(start=0, end=30, value=0, step=1, title="Smoothing by N Days")
        slider.on_change('value', callback)
    
        doc.add_root(column(slider, plot))
    

    Then calling show on that function:

    show(modify_doc)
    

    A full example notebook is here:

    https://github.com/bokeh/bokeh/blob/master/examples/howto/server_embed/notebook_embed.ipynb

  • (Hacky option) some people have combined CustomJS callbacks with Jupyers JS function kernel.execute to propagate values back to the kernel.



来源:https://stackoverflow.com/questions/50826750/how-to-link-a-multiselect-widget-to-a-datatable-using-bokeh-in-a-jupyter-noteboo

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!