Search code examples
pythonpandaswidgetbokehdashboard

Bokeh dashboard layout; widget layout does not show


I am trying to create a Bokeh dashboard and ran into an issue trying to deploy it. Essentially, when the dashboard is launched, the plots will show, but the widgets for interactively updating the plot doesn't. Here is my code:-

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)

And here is the error message I get:-

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

Is there anything additional I need to add into my existing code to fix this and to get both the widgets and plots to deploy?


Solution

  • this is known issue with pandas_bokeh. this error came if you have same plots name but it works when you use curdoc/server type showing. import curdoc and instead of show(bokehlayout), use curdoc().add_root(bokeh_layout) and start bokeh server with bokeh serve --show filename.py about error, mentioned here