holoviz / hvplot

A high-level plotting API for pandas, dask, xarray, and networkx built on HoloViews
https://hvplot.holoviz.org
BSD 3-Clause "New" or "Revised" License
1.08k stars 105 forks source link

Failure to overlay text on bar chart. #1057

Open LinuxIsCool opened 1 year ago

LinuxIsCool commented 1 year ago

ALL software version info

Python 3.10.6 hvplot==0.8.3 holoviews==1.15.4 bokeh==2.4.3 jupyterlab==3.6.3

Description of expected behavior and the observed behavior

Should be able to add text to a bar chart as described here: https://stackoverflow.com/questions/46223037/add-text-annotations-to-each-data-point-in-holoviews-plot

Complete, minimal, self-contained example code that reproduces the issue

import pandas as pd
import hvplot.pandas
import holoviews as hv

df = pd.DataFrame([[1,2,3,4,5]])

df.hvplot.bar() * hv.HLine(df[0].mean()) * hv.Text(1, df[0].mean(), "Mean")
--------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
File ~/.cache/pypoetry/virtualenvs/stakeholderstudy-shsA1FjX-py3.10/lib/python3.10/site-packages/IPython/core/formatters.py:974, in MimeBundleFormatter.__call__(self, obj, include, exclude)
    971     method = get_real_method(obj, self.print_method)
    973     if method is not None:
--> 974         return method(include=include, exclude=exclude)
    975     return None
    976 else:

File ~/.cache/pypoetry/virtualenvs/stakeholderstudy-shsA1FjX-py3.10/lib/python3.10/site-packages/holoviews/core/dimension.py:1290, in Dimensioned._repr_mimebundle_(self, include, exclude)
   1283 def _repr_mimebundle_(self, include=None, exclude=None):
   1284     """
   1285     Resolves the class hierarchy for the class rendering the
   1286     object using any display hooks registered on Store.display
   1287     hooks.  The output of all registered display_hooks is then
   1288     combined and returned.
   1289     """
-> 1290     return Store.render(self)

File ~/.cache/pypoetry/virtualenvs/stakeholderstudy-shsA1FjX-py3.10/lib/python3.10/site-packages/holoviews/core/options.py:1425, in Store.render(cls, obj)
   1423 data, metadata = {}, {}
   1424 for hook in hooks:
-> 1425     ret = hook(obj)
   1426     if ret is None:
   1427         continue

File ~/.cache/pypoetry/virtualenvs/stakeholderstudy-shsA1FjX-py3.10/lib/python3.10/site-packages/holoviews/ipython/display_hooks.py:279, in pprint_display(obj)
    277 if not ip.display_formatter.formatters['text/plain'].pprint:
    278     return None
--> 279 return display(obj, raw_output=True)

File ~/.cache/pypoetry/virtualenvs/stakeholderstudy-shsA1FjX-py3.10/lib/python3.10/site-packages/holoviews/ipython/display_hooks.py:247, in display(obj, raw_output, **kwargs)
    245 elif isinstance(obj, (CompositeOverlay, ViewableElement)):
    246     with option_state(obj):
--> 247         output = element_display(obj)
    248 elif isinstance(obj, (Layout, NdLayout, AdjointLayout)):
    249     with option_state(obj):

File ~/.cache/pypoetry/virtualenvs/stakeholderstudy-shsA1FjX-py3.10/lib/python3.10/site-packages/holoviews/ipython/display_hooks.py:141, in display_hook.<locals>.wrapped(element)
    139 try:
    140     max_frames = OutputSettings.options['max_frames']
--> 141     mimebundle = fn(element, max_frames=max_frames)
    142     if mimebundle is None:
    143         return {}, {}

File ~/.cache/pypoetry/virtualenvs/stakeholderstudy-shsA1FjX-py3.10/lib/python3.10/site-packages/holoviews/ipython/display_hooks.py:187, in element_display(element, max_frames)
    184 if type(element) not in Store.registry[backend]:
    185     return None
--> 187 return render(element)

File ~/.cache/pypoetry/virtualenvs/stakeholderstudy-shsA1FjX-py3.10/lib/python3.10/site-packages/holoviews/ipython/display_hooks.py:68, in render(obj, **kwargs)
     65 if renderer.fig == 'pdf':
     66     renderer = renderer.instance(fig='png')
---> 68 return renderer.components(obj, **kwargs)

File ~/.cache/pypoetry/virtualenvs/stakeholderstudy-shsA1FjX-py3.10/lib/python3.10/site-packages/holoviews/plotting/renderer.py:394, in Renderer.components(self, obj, fmt, comm, **kwargs)
    391 embed = (not (dynamic or streams or self.widget_mode == 'live') or config.embed)
    393 if embed or config.comms == 'default':
--> 394     return self._render_panel(plot, embed, comm)
    395 return self._render_ipywidget(plot)

File ~/.cache/pypoetry/virtualenvs/stakeholderstudy-shsA1FjX-py3.10/lib/python3.10/site-packages/holoviews/plotting/renderer.py:401, in Renderer._render_panel(self, plot, embed, comm)
    399 doc = Document()
    400 with config.set(embed=embed):
--> 401     model = plot.layout._render_model(doc, comm)
    402 if embed:
    403     return render_model(model, comm)

File ~/.cache/pypoetry/virtualenvs/stakeholderstudy-shsA1FjX-py3.10/lib/python3.10/site-packages/panel/viewable.py:509, in Renderable._render_model(self, doc, comm)
    507 if comm is None:
    508     comm = state._comm_manager.get_server_comm()
--> 509 model = self.get_root(doc, comm)
    511 if config.embed:
    512     embed_state(self, model, doc,
    513                 json=config.embed_json,
    514                 json_prefix=config.embed_json_prefix,
    515                 save_path=config.embed_save_path,
    516                 load_path=config.embed_load_path,
    517                 progress=False)

File ~/.cache/pypoetry/virtualenvs/stakeholderstudy-shsA1FjX-py3.10/lib/python3.10/site-packages/panel/viewable.py:560, in Renderable.get_root(self, doc, comm, preprocess)
    543 """
    544 Returns the root model and applies pre-processing hooks
    545 
   (...)
    557 Returns the bokeh model corresponding to this panel object
    558 """
    559 doc = init_doc(doc)
--> 560 root = self._get_model(doc, comm=comm)
    561 if preprocess:
    562     self._preprocess(root)

File ~/.cache/pypoetry/virtualenvs/stakeholderstudy-shsA1FjX-py3.10/lib/python3.10/site-packages/panel/layout/base.py:146, in Panel._get_model(self, doc, root, parent, comm)
    144 if root is None:
    145     root = model
--> 146 objects = self._get_objects(model, [], doc, root, comm)
    147 props = dict(self._init_params(), objects=objects)
    148 model.update(**self._process_param_change(props))

File ~/.cache/pypoetry/virtualenvs/stakeholderstudy-shsA1FjX-py3.10/lib/python3.10/site-packages/panel/layout/base.py:131, in Panel._get_objects(self, model, old_objects, doc, root, comm)
    129 else:
    130     try:
--> 131         child = pane._get_model(doc, root, model, comm)
    132     except RerenderError:
    133         return self._get_objects(model, current_objects[:i], doc, root, comm)

File ~/.cache/pypoetry/virtualenvs/stakeholderstudy-shsA1FjX-py3.10/lib/python3.10/site-packages/panel/pane/holoviews.py:367, in HoloViews._get_model(self, doc, root, parent, comm)
    365     plot = self.object
    366 else:
--> 367     plot = self._render(doc, comm, root)
    369 plot.pane = self
    370 backend = plot.renderer.backend

File ~/.cache/pypoetry/virtualenvs/stakeholderstudy-shsA1FjX-py3.10/lib/python3.10/site-packages/panel/pane/holoviews.py:442, in HoloViews._render(self, doc, comm, root)
    439     if comm:
    440         kwargs['comm'] = comm
--> 442 return renderer.get_plot(self.object, **kwargs)

File ~/.cache/pypoetry/virtualenvs/stakeholderstudy-shsA1FjX-py3.10/lib/python3.10/site-packages/holoviews/plotting/bokeh/renderer.py:70, in BokehRenderer.get_plot(self_or_cls, obj, doc, renderer, **kwargs)
     63 @bothmethod
     64 def get_plot(self_or_cls, obj, doc=None, renderer=None, **kwargs):
     65     """
     66     Given a HoloViews Viewable return a corresponding plot instance.
     67     Allows supplying a document attach the plot to, useful when
     68     combining the bokeh model with another plot.
     69     """
---> 70     plot = super().get_plot(obj, doc, renderer, **kwargs)
     71     if plot.document is None:
     72         plot.document = Document() if self_or_cls.notebook_context else curdoc()

File ~/.cache/pypoetry/virtualenvs/stakeholderstudy-shsA1FjX-py3.10/lib/python3.10/site-packages/holoviews/plotting/renderer.py:236, in Renderer.get_plot(self_or_cls, obj, doc, renderer, comm, **kwargs)
    233     defaults = [kd.default for kd in plot.dimensions]
    234     init_key = tuple(v if d is None else d for v, d in
    235                      zip(plot.keys[0], defaults))
--> 236     plot.update(init_key)
    237 else:
    238     plot = obj

File ~/.cache/pypoetry/virtualenvs/stakeholderstudy-shsA1FjX-py3.10/lib/python3.10/site-packages/holoviews/plotting/plot.py:936, in DimensionedPlot.update(self, key)
    934 def update(self, key):
    935     if len(self) == 1 and ((key == 0) or (key == self.keys[0])) and not self.drawn:
--> 936         return self.initialize_plot()
    937     item = self.__getitem__(key)
    938     self.traverse(lambda x: setattr(x, '_updated', True))

File ~/.cache/pypoetry/virtualenvs/stakeholderstudy-shsA1FjX-py3.10/lib/python3.10/site-packages/holoviews/plotting/bokeh/element.py:2327, in OverlayPlot.initialize_plot(self, ranges, plot, plots)
   2325 if plot and not self.overlaid:
   2326     self._update_plot(key, plot, element)
-> 2327     self._update_ranges(element, ranges)
   2329 panels = []
   2330 for key, subplot in self.subplots.items():

File ~/.cache/pypoetry/virtualenvs/stakeholderstudy-shsA1FjX-py3.10/lib/python3.10/site-packages/holoviews/plotting/bokeh/element.py:898, in ElementPlot._update_ranges(self, element, ranges)
    895     xupdate, yupdate = False, False
    897 if not self.drawn or xupdate:
--> 898     self._update_range(x_range, l, r, xfactors, self.invert_xaxis,
    899                        self._shared['x'], self.logx, streaming)
    900 if not self.drawn or yupdate:
    901     self._update_range(y_range, b, t, yfactors, self.invert_yaxis,
    902                        self._shared['y'], self.logy, streaming)

File ~/.cache/pypoetry/virtualenvs/stakeholderstudy-shsA1FjX-py3.10/lib/python3.10/site-packages/holoviews/plotting/bokeh/element.py:945, in ElementPlot._update_range(self, axis_range, low, high, factors, invert, shared, log, streaming)
    943 factors = list(decode_bytes(factors))
    944 if invert: factors = factors[::-1]
--> 945 axis_range.factors = factors

File ~/.cache/pypoetry/virtualenvs/stakeholderstudy-shsA1FjX-py3.10/lib/python3.10/site-packages/bokeh/core/has_props.py:230, in HasProps.__setattr__(self, name, value)
    228 properties = self.properties(_with_props=True)
    229 if name in properties:
--> 230     return super().__setattr__(name, value)
    232 descriptor = getattr(self.__class__, name, None)
    233 if isinstance(descriptor, property): # Python property

File ~/.cache/pypoetry/virtualenvs/stakeholderstudy-shsA1FjX-py3.10/lib/python3.10/site-packages/bokeh/core/property/descriptors.py:283, in PropertyDescriptor.__set__(self, obj, value, setter)
    280     class_name = obj.__class__.__name__
    281     raise RuntimeError(f"{class_name}.{self.name} is a readonly property")
--> 283 value = self.property.prepare_value(obj, self.name, value)
    284 old = self._get(obj)
    285 self._set(obj, old, value, setter=setter)

File ~/.cache/pypoetry/virtualenvs/stakeholderstudy-shsA1FjX-py3.10/lib/python3.10/site-packages/bokeh/core/property/bases.py:365, in Property.prepare_value(self, owner, name, value, hint)
    363 else:
    364     obj_repr = owner if isinstance(owner, HasProps) else owner.__name__
--> 365     raise ValueError(f"failed to validate {obj_repr}.{name}: {error}")
    367 if isinstance(owner, HasProps):
    368     obj = owner

ValueError: failed to validate FactorRange(id='1159', ...).factors: expected an element of either Seq(String), Seq(Tuple(String, String)) or Seq(Tuple(String, String, String)), got [('0', '0'), ('0', '1'), ('0', '2'), ('0', '3'), ('0', '4'), '1']
hoxbro commented 1 year ago

I can reproduce it with the code given above.

Only plotting the bar returns this: image

Where all bars are plotted over each other. Transposing the DataFrame gives a more desirable look: image

Which is able to be used with hv.Text: image

LinuxIsCool commented 1 year ago

I'm getting a similar problem in a different situation when trying to compose two bar plots using + operator.

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
File ~/.cache/pypoetry/virtualenvs/alloha-S7RXN1yG-py3.10/lib/python3.10/site-packages/panel/viewable.py:591, in Renderable._preprocess(self, root, changed, old_models)
    590 try:
--> 591     hook(self, root, changed, old_models)
    592 except TypeError:

TypeError: link_axes() takes 2 positional arguments but 4 were given

During handling of the above exception, another exception occurred:

ValueError                                Traceback (most recent call last)
File ~/.cache/pypoetry/virtualenvs/alloha-S7RXN1yG-py3.10/lib/python3.10/site-packages/IPython/core/formatters.py:974, in MimeBundleFormatter.__call__(self, obj, include, exclude)
    971     method = get_real_method(obj, self.print_method)
    973     if method is not None:
--> 974         return method(include=include, exclude=exclude)
    975     return None
    976 else:

File ~/.cache/pypoetry/virtualenvs/alloha-S7RXN1yG-py3.10/lib/python3.10/site-packages/holoviews/core/dimension.py:1287, in Dimensioned._repr_mimebundle_(self, include, exclude)
   1280 def _repr_mimebundle_(self, include=None, exclude=None):
   1281     """
   1282     Resolves the class hierarchy for the class rendering the
   1283     object using any display hooks registered on Store.display
   1284     hooks.  The output of all registered display_hooks is then
   1285     combined and returned.
   1286     """
-> 1287     return Store.render(self)

File ~/.cache/pypoetry/virtualenvs/alloha-S7RXN1yG-py3.10/lib/python3.10/site-packages/holoviews/core/options.py:1423, in Store.render(cls, obj)
   1421 data, metadata = {}, {}
   1422 for hook in hooks:
-> 1423     ret = hook(obj)
   1424     if ret is None:
   1425         continue

File ~/.cache/pypoetry/virtualenvs/alloha-S7RXN1yG-py3.10/lib/python3.10/site-packages/holoviews/ipython/display_hooks.py:280, in pprint_display(obj)
    278 if not ip.display_formatter.formatters['text/plain'].pprint:
    279     return None
--> 280 return display(obj, raw_output=True)

File ~/.cache/pypoetry/virtualenvs/alloha-S7RXN1yG-py3.10/lib/python3.10/site-packages/holoviews/ipython/display_hooks.py:251, in display(obj, raw_output, **kwargs)
    249 elif isinstance(obj, (Layout, NdLayout, AdjointLayout)):
    250     with option_state(obj):
--> 251         output = layout_display(obj)
    252 elif isinstance(obj, (HoloMap, DynamicMap)):
    253     with option_state(obj):

File ~/.cache/pypoetry/virtualenvs/alloha-S7RXN1yG-py3.10/lib/python3.10/site-packages/holoviews/ipython/display_hooks.py:142, in display_hook.<locals>.wrapped(element)
    140 try:
    141     max_frames = OutputSettings.options['max_frames']
--> 142     mimebundle = fn(element, max_frames=max_frames)
    143     if mimebundle is None:
    144         return {}, {}

File ~/.cache/pypoetry/virtualenvs/alloha-S7RXN1yG-py3.10/lib/python3.10/site-packages/holoviews/ipython/display_hooks.py:216, in layout_display(layout, max_frames)
    213     max_frame_warning(max_frames)
    214     return None
--> 216 return render(layout)

File ~/.cache/pypoetry/virtualenvs/alloha-S7RXN1yG-py3.10/lib/python3.10/site-packages/holoviews/ipython/display_hooks.py:69, in render(obj, **kwargs)
     66 if renderer.fig == 'pdf':
     67     renderer = renderer.instance(fig='png')
---> 69 return renderer.components(obj, **kwargs)

File ~/.cache/pypoetry/virtualenvs/alloha-S7RXN1yG-py3.10/lib/python3.10/site-packages/holoviews/plotting/renderer.py:397, in Renderer.components(self, obj, fmt, comm, **kwargs)
    394 embed = (not (dynamic or streams or self.widget_mode == 'live') or config.embed)
    396 if embed or config.comms == 'default':
--> 397     return self._render_panel(plot, embed, comm)
    398 return self._render_ipywidget(plot)

File ~/.cache/pypoetry/virtualenvs/alloha-S7RXN1yG-py3.10/lib/python3.10/site-packages/holoviews/plotting/renderer.py:404, in Renderer._render_panel(self, plot, embed, comm)
    402 doc = Document()
    403 with config.set(embed=embed):
--> 404     model = plot.layout._render_model(doc, comm)
    405 if embed:
    406     return render_model(model, comm)

File ~/.cache/pypoetry/virtualenvs/alloha-S7RXN1yG-py3.10/lib/python3.10/site-packages/panel/viewable.py:736, in Viewable._render_model(self, doc, comm)
    734 if comm is None:
    735     comm = state._comm_manager.get_server_comm()
--> 736 model = self.get_root(doc, comm)
    738 if self._design and self._design.theme.bokeh_theme:
    739     doc.theme = self._design.theme.bokeh_theme

File ~/.cache/pypoetry/virtualenvs/alloha-S7RXN1yG-py3.10/lib/python3.10/site-packages/panel/layout/base.py:305, in Panel.get_root(self, doc, comm, preprocess)
    301 def get_root(
    302     self, doc: Optional[Document] = None, comm: Optional[Comm] = None,
    303     preprocess: bool = True
    304 ) -> Model:
--> 305     root = super().get_root(doc, comm, preprocess)
    306     # ALERT: Find a better way to handle this
    307     if hasattr(root, 'styles') and 'overflow-x' in root.styles:

File ~/.cache/pypoetry/virtualenvs/alloha-S7RXN1yG-py3.10/lib/python3.10/site-packages/panel/viewable.py:660, in Renderable.get_root(self, doc, comm, preprocess)
    658     root = self._get_model(doc, comm=comm)
    659     if preprocess:
--> 660         self._preprocess(root)
    661 else:
    662     root = wrapper.get_root(doc, comm, preprocess)

File ~/.cache/pypoetry/virtualenvs/alloha-S7RXN1yG-py3.10/lib/python3.10/site-packages/panel/viewable.py:593, in Renderable._preprocess(self, root, changed, old_models)
    591     hook(self, root, changed, old_models)
    592 except TypeError:
--> 593     hook(self, root)

File ~/.cache/pypoetry/virtualenvs/alloha-S7RXN1yG-py3.10/lib/python3.10/site-packages/panel/pane/holoviews.py:872, in link_axes(root_view, root_model)
    870 if tag in fig.x_range.tags and axis is not fig.x_range:
    871     if hasattr(axis, 'factors'):
--> 872         axis.factors = list(unique_iterator(axis.factors+fig.x_range.factors))
    873     fig.x_range = axis
    874     p.handles['x_range'] = axis

File ~/.cache/pypoetry/virtualenvs/alloha-S7RXN1yG-py3.10/lib/python3.10/site-packages/bokeh/core/has_props.py:327, in HasProps.__setattr__(self, name, value)
    325 properties = self.properties(_with_props=True)
    326 if name in properties:
--> 327     return super().__setattr__(name, value)
    329 descriptor = getattr(self.__class__, name, None)
    330 if isinstance(descriptor, property): # Python property

File ~/.cache/pypoetry/virtualenvs/alloha-S7RXN1yG-py3.10/lib/python3.10/site-packages/bokeh/core/property/descriptors.py:332, in PropertyDescriptor.__set__(self, obj, value, setter)
    329     class_name = obj.__class__.__name__
    330     raise RuntimeError(f"{class_name}.{self.name} is a readonly property")
--> 332 value = self.property.prepare_value(obj, self.name, value)
    333 old = self._get(obj)
    334 self._set(obj, old, value, setter=setter)

File ~/.cache/pypoetry/virtualenvs/alloha-S7RXN1yG-py3.10/lib/python3.10/site-packages/bokeh/core/property/bases.py:364, in Property.prepare_value(self, owner, name, value, hint)
    362 else:
    363     obj_repr = owner if isinstance(owner, HasProps) else owner.__name__
--> 364     raise ValueError(f"failed to validate {obj_repr}.{name}: {error}")
    366 if isinstance(owner, HasProps):
    367     obj = owner

ValueError: failed to validate FactorRange(id='p14208', ...).factors: expected an element of either Seq(String), Seq(Tuple(String, String)) or Seq(Tuple(String, String, String)), got [('0xe6424ab2', 'QF Matched + SME'), ('0xe6424ab2', 'QF Matched'), ('0xe6424ab2', 'QF Unmatched'), ('0x4cd41869', 'QF Matched + SME'), ('0x4cd41869', 'QF Matched'), ('0x4cd41869', 'QF Unmatched'), ('0xdd9b885d', 'QF Matched + SME'), ('0xdd9b885d', 'QF Matched'), ('0xdd9b885d', 'QF Unmatched'), ('0x8d6f0c7b', 'QF Matched + SME'), ('0x8d6f0c7b', 'QF Matched'), ('0x8d6f0c7b', 'QF Unmatched'), ('0xa9bdf738', 'QF Matched + SME'), ('0xa9bdf738', 'QF Matched'), ('0xa9bdf738', 'QF Unmatched'), ('0xe8249a10', 'QF Matched + SME'), ('0xe8249a10', 'QF Matched'), ('0xe8249a10', 'QF Unmatched'), ('0x64a30a4b', 'QF Matched + SME'), ('0x64a30a4b', 'QF Matched'), ('0x64a30a4b', 'QF Unmatched'), ('0x97589cd1', 'QF Matched + SME'), ('0x97589cd1', 'QF Matched'), ('0x97589cd1', 'QF Unmatched'), ('0x23387567', 'QF Matched + SME'), ('0x23387567', 'QF Matched'), ('0x23387567', 'QF Unmatched'), ('0xec026845', 'QF Matched + SME'), ('0xec026845', 'QF Matched'), ('0xec026845', 'QF Unmatched'), ('0xf1f4942d', 'QF Matched + SME'), ('0xf1f4942d', 'QF Matched'), ('0xf1f4942d', 'QF Unmatched'), ('0x72b0d6a6', 'QF Matched + SME'), ('0x72b0d6a6', 'QF Matched'), ('0x72b0d6a6', 'QF Unmatched'), ('0x5351510d', 'QF Matched + SME'), ('0x5351510d', 'QF Matched'), ('0x5351510d', 'QF Unmatched'), ('0x10b3f00e', 'QF Matched + SME'), ('0x10b3f00e', 'QF Matched'), ('0x10b3f00e', 'QF Unmatched'), ('0xc401c980', 'QF Matched + SME'), ('0xc401c980', 'QF Matched'), ('0xc401c980', 'QF Unmatched'), ('0xcf3165f4', 'QF Matched + SME'), ('0xcf3165f4', 'QF Matched'), ('0xcf3165f4', 'QF Unmatched'), '0xe6424ab2', '0x4cd41869', '0xdd9b885d', '0x8d6f0c7b', '0xa9bdf738', '0xe8249a10', '0x64a30a4b', '0x97589cd1', '0x23387567', '0xec026845', '0xf1f4942d', '0x72b0d6a6', '0x5351510d', '0x10b3f00e', '0xc401c980', '0xcf3165f4']

:Layout
   .Bars.I    :Bars   [projectId,Variable]   (value)
   .Overlay.I :Overlay
      .Bars.I  :Bars   [projectId]   (Percentage Boost)
      .HLine.I :HLine   [x,y]
hoxbro commented 1 year ago

Can you share a minimal, reproducible example (MRE)?

LinuxIsCool commented 1 year ago

Can you share a minimal, reproducible example (MRE)?

Yep!

Here you go:

import pandas as pd
import hvplot.pandas
import holoviews as hv

df = pd.DataFrame([[1,2,3,4,5],[1,2,3,4,5]])

df.hvplot.bar(y=['0','1']).opts(multi_level=False) + df.hvplot.bar(y='0')
hoxbro commented 1 year ago

Looking at the error, I can see it happens in Panel, so the fix maybe be needed there. As a work-around for now you can

import pandas as pd
import hvplot.pandas
import holoviews as hv

df = pd.DataFrame([[1,2,3,4,5],[1,2,3,4,5]])

(df.hvplot.bar(y=['0','1']).opts(multi_level=False) + df.hvplot.bar(y='0')).opts(shared_axes=False)

image