I am new to Holoviews and encountering an issue when trying to label a multi-key bar plot.
See my tries below.
My data
import holoviews as hv
import pandas as pd
df = pd.DataFrame(
{
'period': [1, 2, 3, 1, 2, 3],
'origin': ['a', 'a', 'a', 'b', 'b', 'b'],
'value': [3, 5, 5, 1, 2, 4],
}
)
print(df)
period origin value
0 1 a 3
1 2 a 5
2 3 a 5
3 1 b 1
4 2 b 2
5 3 b 4
Direct plotting
Plotting directly without creating hv.Dimension
objects work:
hv.Bars(df, ['origin', 'period'], 'value')
yields the following (see how axes are labelled with dimension codes):
Stacked barplot with labelled Dimensions
Creating dimensions with label, as long as the second label does not have to appear, works:
origin_dim = hv.Dimension('origin', label='Origine')
period_dim = hv.Dimension('period', label='Période')
value_dim = hv.Dimension('value', label='Valeur')
hv.Bars(df, [origin_dim, period_dim], value_dim).opts(stacked=True)
gives me:
Only labelling first dimension
origin_dim = hv.Dimension('origin', label='Origine')
period_dim = hv.Dimension('period')
value_dim = hv.Dimension('value', label='Valeur')
hv.Bars(df, [origin_dim, period_dim], value_dim)
gives (second dimension is not labelled in this example):
Trying to label both key dimensions (does not work)
When trying to label both key dimensions, I get a KeyError exception.
origin_dim = hv.Dimension('origin', label='Origine')
period_dim = hv.Dimension('period', label='Période')
value_dim = hv.Dimension('value', label='Valeur')
hv.Bars(df, [origin_dim, period_dim], value_dim)
raises:
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
/var/lib/anaconda3/envs/py38/lib/python3.8/site-packages/IPython/core/formatters.py in __call__(self, obj, include, exclude)
968
969 if method is not None:
--> 970 return method(include=include, exclude=exclude)
971 return None
972 else:
/var/lib/anaconda3/envs/py38/lib/python3.8/site-packages/holoviews/core/dimension.py in _repr_mimebundle_(self, include, exclude)
1310 combined and returned.
1311 """
-> 1312 return Store.render(self)
1313
1314
/var/lib/anaconda3/envs/py38/lib/python3.8/site-packages/holoviews/core/options.py in render(cls, obj)
1392 data, metadata = {}, {}
1393 for hook in hooks:
-> 1394 ret = hook(obj)
1395 if ret is None:
1396 continue
/var/lib/anaconda3/envs/py38/lib/python3.8/site-packages/holoviews/ipython/display_hooks.py in pprint_display(obj)
280 if not ip.display_formatter.formatters['text/plain'].pprint:
281 return None
--> 282 return display(obj, raw_output=True)
283
284
/var/lib/anaconda3/envs/py38/lib/python3.8/site-packages/holoviews/ipython/display_hooks.py in display(obj, raw_output, **kwargs)
250 elif isinstance(obj, (CompositeOverlay, ViewableElement)):
251 with option_state(obj):
--> 252 output = element_display(obj)
253 elif isinstance(obj, (Layout, NdLayout, AdjointLayout)):
254 with option_state(obj):
/var/lib/anaconda3/envs/py38/lib/python3.8/site-packages/holoviews/ipython/display_hooks.py in wrapped(element)
144 try:
145 max_frames = OutputSettings.options['max_frames']
--> 146 mimebundle = fn(element, max_frames=max_frames)
147 if mimebundle is None:
148 return {}, {}
/var/lib/anaconda3/envs/py38/lib/python3.8/site-packages/holoviews/ipython/display_hooks.py in element_display(element, max_frames)
190 return None
191
--> 192 return render(element)
193
194
/var/lib/anaconda3/envs/py38/lib/python3.8/site-packages/holoviews/ipython/display_hooks.py in render(obj, **kwargs)
66 renderer = renderer.instance(fig='png')
67
---> 68 return renderer.components(obj, **kwargs)
69
70
/var/lib/anaconda3/envs/py38/lib/python3.8/site-packages/holoviews/plotting/renderer.py in components(self, obj, fmt, comm, **kwargs)
393 doc = Document()
394 with config.set(embed=embed):
--> 395 model = plot.layout._render_model(doc, comm)
396 if embed:
397 return render_model(model, comm)
/var/lib/anaconda3/envs/py38/lib/python3.8/site-packages/panel/viewable.py in _render_model(self, doc, comm)
415 if comm is None:
416 comm = state._comm_manager.get_server_comm()
--> 417 model = self.get_root(doc, comm)
418
419 if config.embed:
/var/lib/anaconda3/envs/py38/lib/python3.8/site-packages/panel/viewable.py in get_root(self, doc, comm)
640 """
641 doc = doc or _curdoc()
--> 642 root = self._get_model(doc, comm=comm)
643 self._preprocess(root)
644 ref = root.ref['id']
/var/lib/anaconda3/envs/py38/lib/python3.8/site-packages/panel/layout.py in _get_model(self, doc, root, parent, comm)
118 if root is None:
119 root = model
--> 120 objects = self._get_objects(model, [], doc, root, comm)
121 props = dict(self._init_properties(), objects=objects)
122 model.update(**self._process_param_change(props))
/var/lib/anaconda3/envs/py38/lib/python3.8/site-packages/panel/layout.py in _get_objects(self, model, old_objects, doc, root, comm)
108 else:
109 try:
--> 110 child = pane._get_model(doc, root, model, comm)
111 except RerenderError:
112 return self._get_objects(model, current_objects[:i], doc, root, comm)
/var/lib/anaconda3/envs/py38/lib/python3.8/site-packages/panel/pane/holoviews.py in _get_model(self, doc, root, parent, comm)
225 plot = self.object
226 else:
--> 227 plot = self._render(doc, comm, root)
228
229 plot.pane = self
/var/lib/anaconda3/envs/py38/lib/python3.8/site-packages/panel/pane/holoviews.py in _render(self, doc, comm, root)
284 kwargs = {}
285
--> 286 return renderer.get_plot(self.object, **kwargs)
287
288 def _cleanup(self, root):
/var/lib/anaconda3/envs/py38/lib/python3.8/site-packages/holoviews/plotting/bokeh/renderer.py in get_plot(self_or_cls, obj, doc, renderer, **kwargs)
71 combining the bokeh model with another plot.
72 """
---> 73 plot = super(BokehRenderer, self_or_cls).get_plot(obj, doc, renderer, **kwargs)
74 if plot.document is None:
75 plot.document = Document() if self_or_cls.notebook_context else curdoc()
/var/lib/anaconda3/envs/py38/lib/python3.8/site-packages/holoviews/plotting/renderer.py in get_plot(self_or_cls, obj, doc, renderer, comm, **kwargs)
238 init_key = tuple(v if d is None else d for v, d in
239 zip(plot.keys[0], defaults))
--> 240 plot.update(init_key)
241 else:
242 plot = obj
/var/lib/anaconda3/envs/py38/lib/python3.8/site-packages/holoviews/plotting/plot.py in update(self, key)
924 def update(self, key):
925 if len(self) == 1 and ((key == 0) or (key == self.keys[0])) and not self.drawn:
--> 926 return self.initialize_plot()
927 item = self.__getitem__(key)
928 self.traverse(lambda x: setattr(x, '_updated', True))
/var/lib/anaconda3/envs/py38/lib/python3.8/site-packages/holoviews/plotting/bokeh/element.py in initialize_plot(self, ranges, plot, plots, source)
1374 self.handles['plot'] = plot
1375
-> 1376 self._init_glyphs(plot, element, ranges, source)
1377 if not self.overlaid:
1378 self._update_plot(key, plot, style_element)
/var/lib/anaconda3/envs/py38/lib/python3.8/site-packages/holoviews/plotting/bokeh/element.py in _init_glyphs(self, plot, element, ranges, source)
1318 else:
1319 style = self.style[self.cyclic_index]
-> 1320 data, mapping, style = self.get_data(element, ranges, style)
1321 current_id = element._plot_id
1322
/var/lib/anaconda3/envs/py38/lib/python3.8/site-packages/holoviews/plotting/bokeh/chart.py in get_data(self, element, ranges, style)
1002 if group_dim not in ds.dimensions():
1003 ds = ds.add_dimension(group_dim.name, ds.ndims, gval)
-> 1004 data[group_dim.name].append(ds.dimension_values(group_dim))
1005 else:
1006 data[xdim.name].append(ds.dimension_values(xdim))
/var/lib/anaconda3/envs/py38/lib/python3.8/site-packages/holoviews/core/data/__init__.py in pipelined_fn(*args, **kwargs)
214
215 try:
--> 216 result = method_fn(*args, **kwargs)
217
218 op = method_op.instance(
/var/lib/anaconda3/envs/py38/lib/python3.8/site-packages/holoviews/core/data/__init__.py in dimension_values(self, dimension, expanded, flat)
1068 NumPy array of values along the requested dimension
1069 """
-> 1070 dim = self.get_dimension(dimension, strict=True)
1071 return self.interface.values(self, dim, expanded, flat)
1072
/var/lib/anaconda3/envs/py38/lib/python3.8/site-packages/holoviews/core/dimension.py in get_dimension(self, dimension, default, strict)
970 dims = [d for d in all_dims if dimension == d]
971 if strict and not dims:
--> 972 raise KeyError("%r not found." % dimension)
973 elif dims:
974 return dims[0]
KeyError: "Dimension('period', label='Période') not found."
:Bars [origin,period] (value)
Is using hv.Dimension
labels the correct way to have "pretty" axis labels? Why am I getting a KeyError exception when trying to print my pretty label? How should I proceed to have my plot rendered as a pretty-labelled grouped bar plot?
Thanks to the links provided by @Sander, I was able to find an issue in the Holoviews github repository.
It looks like this is a known bug: https://github.com/holoviz/holoviews/issues/4496