Have dimension labels for 2 key dimensions in a Holoview Bars plot (KeyError: Dimension not found)

Have dimension labels for 2 key dimensions in a Holoview Bars plot (KeyError: Dimension not found)

我是 Holoviews 的新手,在尝试标记多键条形图时遇到问题。

查看下面我的尝试。

我的数据

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

直接出图

直接绘图而不创建 hv.Dimension 个对象有效:

hv.Bars(df, ['origin', 'period'], 'value')

产生以下结果(查看轴如何用尺寸代码标记):

带有标签维度的堆叠条形图

创建带有标签的维度,只要第二个标签不必出现,就可以:

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)

给我:

只标注第一个维度

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)

给出(此示例中未标记第二个维度):

尝试标记两个关键维度(不起作用)

尝试标记两个关键维度时,出现 KeyError 异常。

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)

加注:

---------------------------------------------------------------------------
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)

使用 hv.Dimension 标签是否是获得“漂亮”轴标签的正确方法?为什么在尝试打印漂亮标签时出现 KeyError 异常?我应该如何继续将我的绘图呈现为带有漂亮标签的分组条形图?

您可以在绘图上使用 .opts() 来更改 xlabel。
这是让你的情节看起来更好的好方法。
另见:http://holoviews.org/user_guide/Customizing_Plots.html

示例代码:

hv.Bars(
    df, 
    ['origin', 'period'], 
    ['value']
).opts(xlabel='Origine, Periode')

但是你写的方式应该也可以,我认为这可能是一个错误。
您也可以 post 在 HoloViews 论坛上提出您的问题:https://discourse.holoviz.org/
或者在这里创建一个问题:https://github.com/holoviz/holoviews/issues

您还可以使用由相同开发人员在 HoloViews 之上构建的 hvplot 来更轻松地创建相同类型的绘图:

import hvplot.pandas

df.hvplot.bar(
    x='origin', 
    y='value', 
    by='period', 
).opts(xlabel='Origine, Periode')

结果图:

感谢@Sander 提供的链接,我能够在 Holoviews github 存储库中找到一个问题。

看起来这是一个已知错误: https://github.com/holoviz/holoviews/issues/4496