【问题标题】:How to link a multiselect widget to a datatable using bokeh in a jupyter notebook?如何在 jupyter 笔记本中使用散景将多选小部件链接到数据表?
【发布时间】:2018-11-22 10:00:33
【问题描述】:

我正在尝试将数据表与散景中的多选小部件连接起来。我四处搜索并收集到我需要开发一个函数来更新数据表的数据源,但我似乎有两个问题。

  1. 单击多选对象后,我似乎无法访问它的值。
  2. 收到更改后,我似乎无法将更改推送到笔记本。

这是我的代码示例:

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)

【问题讨论】:

  • 恐怕你只能在 Jupyter 笔记本上使用 JavaScript 回调(CustomJS)。如果你想使用 python 回调,那么你需要将 bokeh 作为服务器应用程序运行(使用bokeh serve)
  • 我认为从笔记本更新散景图可以正常工作(请参阅documentation),但散景小部件(多选)不起作用。显然您可以使用 jupyter 小部件进行交互 (next point in the same documentation)
  • @ChesuCR 在笔记本中嵌入带有真正 python 回调的完整散景服务器应用程序已经有一段时间了。见:github.com/bokeh/bokeh/blob/master/examples/howto/server_embed/…

标签: python datatable jupyter-notebook bokeh multi-select


【解决方案1】:

push_notebook 是单向的。也就是说,您只能将更改从 IPython 内核推送到 JavaScript 前端。 UI 的任何更改都不会传播回正在运行的 Python 内核。换句话说,on_change 没用(没有更多工作,见下文)如果你想要那种交互,有几个选项:

  • 将ipywidgets 与push_notebook 一起使用。通常这涉及到 interact 函数自动生成一个简单的 UI,该 UI 带有回调,使用 push_notebook 根据小部件值更新绘图等。需要说明的是,这种方法使用ipywidgets,它们是不是 Bokeh 内置小部件。您可以在此处查看完整的示例笔记本:

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

  • 嵌入 Bokeh 服务器应用程序。 Bokeh 服务器使 Bokeh 小部件上的 on_change 回调能够正常工作。通常这涉及创建一个定义应用程序的函数(通过指定如何创建新文档):

    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))
    

    然后在该函数上调用show:

    show(modify_doc)
    

    这里有一个完整的示例笔记本:

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

  • (Hacky 选项)有些人将 CustomJS 回调与 Jupyers JS 函数 kernel.execute 结合起来将值传播回内核。

【讨论】:

    猜你喜欢
    • 2018-08-06
    • 1970-01-01
    • 1970-01-01
    • 2018-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-01
    • 1970-01-01
    相关资源
    最近更新 更多