Error when no data: bokeh backend could not plot any Elements in the Overlay
Software Version Info
panel: 1.6.0
os: fedora
browser: chrome
Similar behavior on pandas and duckdb as a source.
Description of expected behavior and the observed behavior
I want to have a grid of subplots divided by year and month. I have also a checkbox group, so I can decide what data I want to see on the plot. For some of the values in checkbox there is no data for particular year / month. In that case there is an error.
The same behavior if I implement this by pn.GridBox and add each scatter plot separately to the grid with the loop.
Complete, minimal, self-contained example code that reproduces the issue
import pandas as pd
import hvplot.pandas
import panel as pn
my_data = pd.DataFrame(
{
'date': ['2023-05-08', '2023-05-18', '2023-06-21', '2023-07-01', '2024-05-01', '2024-06-01', '2024-06-03', '2024-07-06', '2024-07-21'],
'type': ['A', 'B', 'A', 'A', 'A', 'B', 'A', 'A', 'B'],
'value': [5, 4, 3, 2, 4, 8, 2, 2, 8]
}
)
my_data['date'] = pd.to_datetime(my_data['date'])
my_data['date_year'] = my_data['date'].dt.year
my_data['date_month'] = my_data['date'].dt.month
pn.extension(theme='dark')
tickers_list = my_data['type'].unique().tolist()
ticker_group = pn.widgets.CheckBoxGroup(name='', value=['A',], options=tickers_list, inline=False, width=50)
def col_row_chart(data:pd.DataFrame, types):
# too many charts kill the app, only last three years to show
# this chart doesn't work if there are other charts on the same webpage
data = data[data['type'].isin(types)]
return data.hvplot.scatter(x='date', y='value', by='type', row='date_year', col='date_month', xaxis=False,
yaxis=True)
bound_dividends_tickers = pn.bind(col_row_chart, data=my_data, types=ticker_group)
dividends_layout = pn.Row(name='Dividends', sizing_mode='stretch_both')
dividends_layout.append(ticker_group)
dividends_layout.append(bound_dividends_tickers)
dividends_layout.servable()
Stack traceback and/or browser JavaScript console output
2025-02-17 20:58:54,110 ERROR: panel.reactive - Callback failed for object named '' changing property {'value': ['B']}
Traceback (most recent call last):
File "/matt/projekty/python/panel-intro/.venv/lib/python3.10/site-packages/panel/reactive.py", line 470, in _process_events
self.param.update(**self_params)
File "/matt/projekty/python/panel-intro/.venv/lib/python3.10/site-packages/param/parameterized.py", line 2406, in update
restore = dict(self_._update(arg, **kwargs))
File "/matt/projekty/python/panel-intro/.venv/lib/python3.10/site-packages/param/parameterized.py", line 2439, in _update
self_._batch_call_watchers()
File "/matt/projekty/python/panel-intro/.venv/lib/python3.10/site-packages/param/parameterized.py", line 2624, in _batch_call_watchers
self_._execute_watcher(watcher, events)
File "/matt/projekty/python/panel-intro/.venv/lib/python3.10/site-packages/param/parameterized.py", line 2586, in _execute_watcher
watcher.fn(*args, **kwargs)
File "/matt/projekty/python/panel-intro/.venv/lib/python3.10/site-packages/panel/param.py", line 897, in _replace_pane
self._update_inner(new_object)
File "/matt/projekty/python/panel-intro/.venv/lib/python3.10/site-packages/panel/pane/base.py", line 743, in _update_inner
new_pane, internal = self._update_from_object(
File "/matt/projekty/python/panel-intro/.venv/lib/python3.10/site-packages/panel/pane/base.py", line 732, in _update_from_object
old_object.object = object
File "/matt/projekty/python/panel-intro/.venv/lib/python3.10/site-packages/param/parameterized.py", line 515, in _f
instance_param.__set__(obj, val)
File "/matt/projekty/python/panel-intro/.venv/lib/python3.10/site-packages/param/parameterized.py", line 517, in _f
return f(self, obj, val)
File "/matt/projekty/python/panel-intro/.venv/lib/python3.10/site-packages/param/parameterized.py", line 1564, in __set__
obj.param._call_watcher(watcher, event)
File "/matt/projekty/python/panel-intro/.venv/lib/python3.10/site-packages/param/parameterized.py", line 2604, in _call_watcher
self_._execute_watcher(watcher, (event,))
File "/matt/projekty/python/panel-intro/.venv/lib/python3.10/site-packages/param/parameterized.py", line 2586, in _execute_watcher
watcher.fn(*args, **kwargs)
File "/matt/projekty/python/panel-intro/.venv/lib/python3.10/site-packages/panel/pane/base.py", line 430, in _update_pane
self._update_object(ref, doc, root, parent, comm)
File "/matt/projekty/python/panel-intro/.venv/lib/python3.10/site-packages/panel/pane/base.py", line 351, in _update_object
new_model = self._get_model(doc, root, parent, comm)
File "/matt/projekty/python/panel-intro/.venv/lib/python3.10/site-packages/panel/pane/holoviews.py", line 437, in _get_model
plot = self._render(doc, comm, root)
File "/matt/projekty/python/panel-intro/.venv/lib/python3.10/site-packages/panel/pane/holoviews.py", line 531, in _render
return renderer.get_plot(self.object, **kwargs)
File "/matt/projekty/python/panel-intro/.venv/lib/python3.10/site-packages/holoviews/plotting/bokeh/renderer.py", line 68, in get_plot
plot = super().get_plot(obj, doc, renderer, **kwargs)
File "/matt/projekty/python/panel-intro/.venv/lib/python3.10/site-packages/holoviews/plotting/renderer.py", line 234, in get_plot
plot = self_or_cls.plotting_class(obj)(obj, renderer=renderer,
File "/matt/projekty/python/panel-intro/.venv/lib/python3.10/site-packages/holoviews/plotting/bokeh/plot.py", line 505, in __init__
self.subplots, self.layout = self._create_subplots(layout, ranges)
File "/matt/projekty/python/panel-intro/.venv/lib/python3.10/site-packages/holoviews/plotting/bokeh/plot.py", line 585, in _create_subplots
subplot = plotting_class(view, dimensions=self.dimensions,
File "/matt/projekty/python/panel-intro/.venv/lib/python3.10/site-packages/holoviews/plotting/bokeh/element.py", line 3075, in __init__
super().__init__(overlay, **kwargs)
File "/matt/projekty/python/panel-intro/.venv/lib/python3.10/site-packages/holoviews/plotting/plot.py", line 1768, in __init__
self.subplots = self._create_subplots(ranges)
File "/matt/projekty/python/panel-intro/.venv/lib/python3.10/site-packages/holoviews/plotting/plot.py", line 1844, in _create_subplots
raise SkipRendering(f"{self.renderer.backend} backend could not plot any Elements "
holoviews.core.options.SkipRendering: bokeh backend could not plot any Elements in the Overlay.
Screenshots or screencasts of the bug in action
As long as A is selected it works fine.
Additional issue: take a look how this plot looks like on the web browser. date_year is not well positioned. If I use sizing_mode='stretch_width' it will look even worse.
Then select A and B and unselect A:
The error will occur (above).
- [ ] I may be interested in making a pull request to address this
This issue has been mentioned on HoloViz Discourse. There might be relevant details there:
https://discourse.holoviz.org/t/show-plot-when-there-is-no-data/8584/3
This error seems to happen because the GridSpace contains empty NdLayouts:
import pandas as pd
import hvplot.pandas
import panel as pn
df = pd.DataFrame(
{
'date': ['2023-05-08', '2023-05-18', '2023-06-21', '2023-07-01', '2024-05-01', '2024-06-01', '2024-06-03', '2024-07-06', '2024-07-21'],
'type': ['A', 'B', 'A', 'A', 'A', 'B', 'A', 'A', 'B'],
'value': [5, 4, 3, 2, 4, 8, 2, 2, 8]
}
)
df['date'] = pd.to_datetime(df['date'])
df['date_year'] = df['date'].dt.year
df['date_month'] = df['date'].dt.month
sdf = df[df['type'].isin(['B'])]
plot = sdf.hvplot.scatter(
x='date', y='value', by='type', row='date_year', col='date_month',
xaxis=False, yaxis=True,
)
A workaround is to use color='type' instead of by='type', this avoids creating NdOverlays, by-passing the issue entirely.
Setting dynamic=False also helps. Internally, hvPlot creates a DynamicMap as a result of a groupby operation with dynamic=True. It then calls .grid(<dims>) on this object. I tend to think that, when the output is meant to be a GridSpace, creating internally a DynamicMap instead of a HoloMap isn't very useful? cc @hoxbro
Additional issue: take a look how this plot looks like on the web browser.
date_yearis not well positioned. If I usesizing_mode='stretch_width'it will look even worse.
This is a known issue tracked in HoloViews, see https://github.com/holoviz/holoviews/issues/5438.
I tend to think that, when the output is meant to be a GridSpace, creating internally a DynamicMap instead of a HoloMap isn't very useful? cc @hoxbro
It doesn't seem useful to me either, but it is hard to say without looking at the code.