散景仪表板布局;小部件布局不显示

Posted

技术标签:

【中文标题】散景仪表板布局;小部件布局不显示【英文标题】:Bokeh dashboard layout; widget layout does not show 【发布时间】:2021-11-16 05:16:32 【问题描述】:

我正在尝试创建 Bokeh 仪表板,但在尝试部署它时遇到了问题。本质上,当仪表板启动时,绘图将显示,但用于交互式更新绘图的小部件不会。这是我的代码:-

import numpy as np
import pandas as pd
import pandas_bokeh 
from bokeh.io import show
from bokeh.layouts import column, layout, row
from bokeh.models import DateRangeSlider, Dropdown

#color palette
colors=['#FDE724','#D01C8B','#4DAC26']

#define the categorical variable
category_a = ['A','B','C']
category_b = ['X','Y','Z']

#set random seed to make the dataset reproducible
np.random.seed(42)
#create a dataset
#df_random = pd.DataFrame(
#   'id': np.arange(0, 15),
#   'month':np.random.randint(1, 12, 15),
#   'sensor_1': np.random.uniform(0, 1,15),
#   'sensor_2': np.random.uniform(10, 15, 15),
#   'sensor_3': np.random.randint(0, 20, 15),
#   'category': np.random.choice(category, 15, p=[0.2, 0.4, 0.4]),
#)

df_random2 = pd.DataFrame(
   'id': np.arange(0, 30),
   'date': pd.date_range(start='1/1/2021', periods=30, freq='D'),
   'month':np.random.randint(1, 12, 30),
   'sensor_1': np.random.uniform(0, 1,30),
   'sensor_2': np.random.uniform(10, 15, 30),
   'sensor_3': np.random.randint(0, 20, 30),
   'categorya': np.random.choice(category_a, 30, p=[0.2, 0.4, 0.4]),
   'categoryb': np.random.choice(category_b, 30, p=[0.6, 0.2, 0.2]),
)
#set index to id column
df_random2=df_random2.set_index('id')

df_random2.shape

df_random2.head()

mindate=df_random2['date'].min()
maxdate=df_random2['date'].max()

menucols = [("Category A", "categorya"),("Category B","categoryb")]

date_range_slider = DateRangeSlider(value=(mindate, maxdate),
                                    start=mindate, end=maxdate)

category_picker = Dropdown(label = "Column select", button_type="default", menu=menucols)

# Plot1 - Line plot
p_line= df_random2.groupby(['date']).mean().plot_bokeh(kind="line",y="sensor_2",color='#d01c8b',plot_data_points=True,show_figure=False)
# Plot2- Barplot
p_bar = df_random2.groupby(['date']).mean().plot_bokeh(kind="bar",y='sensor_2', colormap=colors,show_figure=False)

# Plot3- stacked bar chart
df_sensor=df_random2.drop(['date','month','categorya'],axis=1)
p_stack=df_sensor.groupby(['categoryb']).mean().plot_bokeh(kind='barh', stacked=True,colormap=colors,show_figure=False)

#Plot4- Scatterplot
p_scatter = df_random2.plot_bokeh(kind="scatter", x="month", y="sensor_2",category="categoryb",colormap=colors,show_figure=False)
#Plot5- Pie chart
p_pie= df_random2.groupby(['categoryb']).mean().plot_bokeh.pie(y='sensor_1',colormap=colors,show_figure=False)

#Plot6- Histogram
p_hist=df_sensor.plot_bokeh(kind='hist', histogram_type="stacked",bins=6,colormap=colors, show_figure=False)

widgets = [date_range_slider,category_picker]


#Make Dashboard with Grid Layout: 
plots=pandas_bokeh.plot_grid([[p_line, p_bar,p_stack],[p_scatter, p_pie,p_hist]], plot_width=400)


bokehlayout = layout(widgets,plots)

show(bokehlayout)

这是我收到的错误消息:-

RuntimeError: Models must be owned by only a single document, HoverTool(id='2836', ...) is already in a doc
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
m:\bokehdash\exploratorydatanalysis.py in <module>
     83 bokehlayout = layout(widgets,plots)
     84 
---> 85 show(bokehlayout)

~\anaconda3\lib\site-packages\bokeh\io\showing.py in show(obj, browser, new, notebook_handle, notebook_url, **kw)
    137         return run_notebook_hook(state.notebook_type, 'app', obj, state, notebook_url, **kw)
    138 
--> 139     return _show_with_state(obj, state, browser, new, notebook_handle=notebook_handle)
    140 
    141 #-----------------------------------------------------------------------------

~\anaconda3\lib\site-packages\bokeh\io\showing.py in _show_with_state(obj, state, browser, new, notebook_handle)
    175 
    176     if state.file or not shown:
--> 177         _show_file_with_state(obj, state, new, controller)
    178 
    179     return comms_handle

~\anaconda3\lib\site-packages\bokeh\io\showing.py in _show_file_with_state(obj, state, new, controller)
    158 
    159     '''
--> 160     filename = save(obj, state=state)
    161     controller.open("file://" + filename, new=NEW_PARAM[new])
    162 

~\anaconda3\lib\site-packages\bokeh\io\saving.py in save(obj, filename, resources, title, template, state, **kwargs)
     84 
     85     filename, resources, title = _get_save_args(state, filename, resources, title)
---> 86     _save_helper(obj, filename, resources, title, template, theme)
     87     return abspath(filename)
     88 

~\anaconda3\lib\site-packages\bokeh\io\saving.py in _save_helper(obj, filename, resources, title, template, theme)
    146     '''
    147     from ..embed import file_html
--> 148     html = file_html(obj, resources, title=title, template=template, theme=theme)
    149 
    150     with open(filename, mode="w", encoding="utf-8") as f:

~\anaconda3\lib\site-packages\bokeh\embed\standalone.py in file_html(models, resources, title, template, template_variables, theme, suppress_callback_warning, _always_new)
    301         models_seq = models
    302 
--> 303     with OutputDocumentFor(models_seq, apply_theme=theme, always_new=_always_new) as doc:
    304         (docs_json, render_items) = standalone_docs_json_and_render_items(models_seq, suppress_callback_warning=suppress_callback_warning)
    305         title = _title_from_models(models_seq, title)

~\anaconda3\lib\contextlib.py in __enter__(self)
    111         del self.args, self.kwds, self.func
    112         try:
--> 113             return next(self.gen)
    114         except StopIteration:
    115             raise RuntimeError("generator didn't yield") from None

~\anaconda3\lib\site-packages\bokeh\embed\util.py in OutputDocumentFor(objs, apply_theme, always_new)
    132             doc = Document()
    133             for model in objs:
--> 134                 doc.add_root(model)
    135 
    136         # handle a single shared document

~\anaconda3\lib\site-packages\bokeh\document\document.py in add_root(self, model, setter)
    319             self._roots.append(model)
    320         finally:
--> 321             self._pop_all_models_freeze()
    322         self._trigger_on_change(RootAddedEvent(self, model, setter))
    323 

~\anaconda3\lib\site-packages\bokeh\document\document.py in _pop_all_models_freeze(self)
   1102         self._all_models_freeze_count -= 1
   1103         if self._all_models_freeze_count == 0:
-> 1104             self._recompute_all_models()
   1105 
   1106     def _recompute_all_models(self):

~\anaconda3\lib\site-packages\bokeh\document\document.py in _recompute_all_models(self)
   1125             d._detach_document()
   1126         for a in to_attach:
-> 1127             a._attach_document(self)
   1128         self._all_models = recomputed
   1129         self._all_models_by_name = recomputed_by_name

~\anaconda3\lib\site-packages\bokeh\model.py in _attach_document(self, doc)
    690         '''
    691         if self._document is not None and self._document is not doc:
--> 692             raise RuntimeError("Models must be owned by only a single document, %r is already in a doc" % (self))
    693         doc.theme.apply_to_model(self)
    694         self._document = doc

RuntimeError: Models must be owned by only a single document, HoverTool(id='2836', ...) is already in a doc

我是否需要在现有代码中添加任何其他内容来解决此问题并同时部署小部件和绘图?

【问题讨论】:

【参考方案1】:

这是 pandas_bokeh 的已知问题。如果您具有相同的绘图名称,则会出现此错误,但是当您使用 curdoc/server 类型显示时它会起作用。 import curdoc 而不是show(bokehlayout),使用curdoc().add_root(bokeh_layout) 并使用bokeh serve --show filename.py 启动散景服务器 关于错误,提到了here

【讨论】:

感谢您的建议。我已修改我的代码以使用 import curdoc 等。但是当我在 powershell 中启动应用程序时,只会打开一个空白浏览器窗口。这可能是什么原因造成的? 使用 curdoc 对我来说一切都很好。小部件和绘图 抱歉,你说得对,它确实有效。在我的最后做了一个轻微的错字。谢谢你:)

以上是关于散景仪表板布局;小部件布局不显示的主要内容,如果未能解决你的问题,请参考以下文章

颤振小部件不显示

有没有办法将小部件显示为两个不同的选项卡?

在 Qtabwidget 中扩展小部件

散景小部件不更新情节

设计小部件布局

膨胀相对布局时出错