通过选择小部件在Jupyter Notebook上进行交互式选择会引发“模型必须仅由单个文档拥有”错误

时间:2019-02-17 18:00:25

标签: python widget bokeh

如何通过Jupyter Notebook上的a selection widget用bokeh创建交互式散景图?

为什么笔记本会出现以下错误:

“ RuntimeError:模型必须仅由单个文档拥有,文档中的Title(id ='1044',...) 错误:tornado.access:500 GET /autoload.js?bokeh-autoload-element=1002&bokeh-absolute-url=http://localhost:54277&resources=none(:: 1)117.01ms“

我仔细阅读了github的这个示例和Google Bokeh Group的类似情况,在后者中,他们运行的是bokeh服务器,而不是jupyter内核。

output_notebook()

dct={'Date' : ["2018-01-07", "2018-01-12", "2018-01-13", "2018-01-14", "2018-01-20", "2018-01-24"],'Activity' : ['A','B','A','B','A','B'],'Count' : [1, 2, 5, 3, 7, 1]}
df=pd.DataFrame(dct)

activity_list=df['Activity'].unique().tolist().copy()
activity_selected='A'
def modify_doc(doc):
     def make_plot(cdf):
         plot = figure()
         plot.vbar(x=cdf.Date, top=cdf.Count, width=0.9)
         push_notebook()
         show(plot, notebook_handle = True)
         return plot
     def update_plot(attr, old, new):
         activity =  select.value
         sdf = df.copy()
         sdf = sdf[sdf['Activity'] == activity]
         layout.children[0] = make_plot(sdf)


     select = Select(title='Select Activity', value=activity_selected, options=activity_list)
     select.on_change('value', update_plot)
     p=make_plot(df)
     layout=column(select, p)
     doc.add_root(layout)
show(modify_doc)

我期望的快照中是这样的:

enter image description here

我正在使用Bokeh 1.0.4

2 个答案:

答案 0 :(得分:1)

我们可能需要对文档进行一些改进,因为您的代码中有些部分没有意义。

  • push_notebook是对显示真实的Bokeh服务器应用程序的补充(即,将modify_doc传递给show)。我想不起来将它们一起使用的任何情况。 Bokeh服务器应用程序功能是push_notebook的严格超集,因此,既然您已经在制作Bokeh服务器应用程序,则应该以标准方式更新所有内容。

  • show绝不能在Bokeh服务器应用代码的内部 中被调用(在这种情况下,在modify_doc内部),这实际上是导致异常的直接原因你越来越。你应该

  • 您不应该每次都绘制新图! push_notebook和Bokeh服务器的全部目的是可以高效地进行更新,而不必每次都创建一个新的情节。您应该更新现有图的数据和属性。

这里有一个笔记本中Bokeh服务器应用程序的完整示例:

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

您应该研究并模仿它,因为它代表了最佳实践。

答案 1 :(得分:0)

通过Select小部件选择图的正确代码是:

activity_list=df['Activity'].unique().tolist().copy()
df['Date']=pd.to_datetime(df['Date'])

activity_selected='A'

def modify_doc(doc):

    df_r=df.copy()
    source = ColumnDataSource(data=df_r)
    plot=figure(title='Daily Hours',x_axis_type="datetime")
    plot.vbar(x="Date", top="Count",source=source, width=4)
    def update_plot(attr, old, new):
        activity =  select.value
        data = df_r[df_r['Activity'] == activity]
        source.data = ColumnDataSource(data=data).data

    select = Select(title='Select Activity', value=activity_selected, options=activity_list)
    select.on_change('value', update_plot)

    layout=column(select, plot)
    doc.add_root(layout)
show(modify_doc)

这将是您看到的输出:

enter image description here enter image description here