hvplot icon indicating copy to clipboard operation
hvplot copied to clipboard

color not working for bar plot with Plotly backend

Open MarcSkovMadsen opened this issue 1 year ago • 3 comments

I would expect the color argument to work the same for the Bokeh and Plotly plotting backends when plotting a bar plot. But they don't.

image

import pandas as pd
import hvplot.pandas  # noqa

hvplot.extension("bokeh")
pd.DataFrame({
    "framework": ["hvPlot", "HoloViews", "Panel"], 
    "stars": [700, 2400, 2600]
}).hvplot.bar(x="framework", y="stars", color="gold", title="Bar Plot of Github Stars as of March 2023", ylabel="⭐")

hvplot.extension("plotly")
pd.DataFrame({
    "framework": ["hvPlot", "HoloViews", "Panel"], 
    "stars": [700, 2400, 2600]
}).hvplot.bar(x="framework", y="stars", color="gold", title="Bar Plot of Github Stars as of March 2023", ylabel="⭐")

MarcSkovMadsen avatar Mar 11 '23 20:03 MarcSkovMadsen

If you try to use a list of colors it raises an exception

image

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In [9], line 2
      1 hvplot.extension("plotly")
----> 2 autompg_wide.hvplot.bar(y=['Asia', 'Europe', 'North America'], width=1000, ylabel="mpg", color=["#ba2649", "#ffa7ca", "#1a6b54"], rot=90)

File c:\repos\private\hvplot\hvplot\plotting\core.py:1046, in hvPlotTabular.bar(self, x, y, **kwds)
    959 def bar(self, x=None, y=None, **kwds):
    960     """
    961     A vertical bar plot
    962 
   (...)
   1044     - Wiki: https://en.wikipedia.org/wiki/Bar_chart
   1045     """
-> 1046     return self(x, y, kind="bar", **kwds)

File c:\repos\private\hvplot\hvplot\plotting\core.py:92, in hvPlotBase.__call__(self, x, y, kind, **kwds)
     89         plot = self._get_converter(x, y, kind, **kwds)(kind, x, y)
     90         return pn.panel(plot, **panel_dict)
---> 92 return self._get_converter(x, y, kind, **kwds)(kind, x, y)

File c:\repos\private\hvplot\hvplot\converter.py:1252, in HoloViewsConverter.__call__(self, kind, x, y)
   1250 if not (self.datashade or self.rasterize):
   1251     layers = self._apply_layers(obj)
-> 1252     layers = _transfer_opts_cur_backend(layers)
   1253     return layers
   1254 try:

File c:\repos\private\hvplot\hvplot\backend_transforms.py:88, in _transfer_opts_cur_backend(element)
     86 def _transfer_opts_cur_backend(element):
     87     if Store.current_backend != 'bokeh':
---> 88         element = element.apply(_transfer_opts, backend=Store.current_backend)
     89     return element

File c:\repos\private\tmp\holoviews\holoviews\core\accessors.py:45, in AccessorPipelineMeta.pipelined.<locals>.pipelined_call(*args, **kwargs)
     42     inst._obj._in_method = True
     44 try:
---> 45     result = __call__(*args, **kwargs)
     47     if not in_method:
     48         init_op = factory.instance(
     49             output_type=type(inst),
     50             kwargs={'mode': getattr(inst, 'mode', None)},
     51         )

File c:\repos\private\tmp\holoviews\holoviews\core\accessors.py:202, in Apply.__call__(self, apply_function, streams, link_inputs, link_dataset, dynamic, per_element, **kwargs)
    200 if hasattr(apply_function, 'dynamic'):
    201     inner_kwargs['dynamic'] = False
--> 202 new_obj = apply_function(self._obj, **inner_kwargs)
    203 if (link_dataset and isinstance(self._obj, Dataset) and
    204     isinstance(new_obj, Dataset) and new_obj._dataset is None):
    205     new_obj._dataset = self._obj.dataset

File c:\repos\private\hvplot\hvplot\backend_transforms.py:52, in _transfer_opts(element, backend)
     50     continue
     51 elif transform:
---> 52     opt, val = transform(opt, val)
     53     if val is UNSET:
     54         continue

File c:\repos\private\hvplot\hvplot\backend_transforms.py:314, in <lambda>(k, v)
    287 # Plotly transforms
    289 _line_dash_bk_plotly_mapping = {
    290     'solid': 'solid',
    291     'dashed': 'dash',
   (...)
    294     'dashdot': 'dashdot',
    295 }
    297 PLOTLY_TRANSFORMS = {
    298     'plot': {
    299         'alpha': lambda k, v: ('opacity', v),
    300         'min_height': UNSET,
    301         'min_width': UNSET,
    302         'max_height': UNSET,
    303         'max_width': UNSET,
    304         'frame_width': UNSET,
    305         'frame_height': UNSET,
    306         'batched': UNSET,
    307         'legend_limit': UNSET,
    308         'tools': UNSET,
    309         'shared_xaxis': UNSET,
    310         'shared_yaxis': UNSET,
    311     },
    312     'style': {
    313         'alpha': lambda k, v: ('opacity', v),
--> 314         'color': lambda k, v: (k, COLOR_ALIASES.get(v, v)),
    315         'fill_color': lambda k, v: ('fillcolor', COLOR_ALIASES.get(v, v)),
    316         'line_color': lambda k, v: (k, COLOR_ALIASES.get(v, v)),
    317         'line_dash': lambda k, v: ('dash', _line_dash_bk_plotly_mapping.get(v, UNSET)),
    318         'line_width': lambda k, v: ('line_width', v),
    319         'muted_alpha': UNSET,
    320         'palette': UNSET,
    321     }
    322 }
    325 BACKEND_TRANSFORMS = dict(
    326     matplotlib=MATPLOTLIB_TRANSFORMS,
    327     plotly=PLOTLY_TRANSFORMS,
    328 )

TypeError: unhashable type: 'list'

If you try to use the values of a column it does not work either.

image

import pandas as pd
import hvplot.pandas  # noqa

hvplot.extension("plotly")

from bokeh.sampledata.autompg import autompg_clean as autompg

autompg.head()

autompg_long_form = autompg.groupby("yr").mean(numeric_only=True).reset_index()
autompg_long_form.head()

autompg_multi_index = autompg.query("yr<=80").groupby(['yr', 'origin']).mean(numeric_only=True)
autompg_multi_index.head()
autompg_wide = autompg_multi_index.reset_index().pivot(index='yr', columns='origin', values='mpg')
autompg_wide.head()

hvplot.extension("bokeh")
autompg_wide.hvplot.bar(y=['Asia', 'Europe', 'North America'], width=1000, ylabel="mpg", color=["#ba2649", "#ffa7ca", "#1a6b54"], rot=90)

hvplot.extension("plotly")
autompg_wide.hvplot.bar(y=['Asia', 'Europe', 'North America'], width=1000, ylabel="mpg", color=["#ba2649", "#ffa7ca", "#1a6b54"], rot=90)

hvplot.extension("bokeh")
autompg_long_form.hvplot.bar(y='mpg', color="weight", colorbar=True, clabel="Weight", cmap="bmy", width=1000)

hvplot.extension("plotly")
autompg_long_form.hvplot.bar(y='mpg', color="weight", colorbar=True, clabel="Weight", cmap="bmy", width=1000)

MarcSkovMadsen avatar Mar 11 '23 20:03 MarcSkovMadsen

The issue seems to originate from HoloViews. I've reported the HoloViews bug here https://github.com/holoviz/holoviews/issues/5658

MarcSkovMadsen avatar Mar 12 '23 18:03 MarcSkovMadsen

Just got hit by this again

image

MarcSkovMadsen avatar Dec 23 '23 07:12 MarcSkovMadsen