holoviz / holoviews

With Holoviews, your data visualizes itself.
https://holoviews.org
BSD 3-Clause "New" or "Revised" License
2.66k stars 397 forks source link

Count aggregation on object column failing on heatmap #5508

Open ajstewart opened 1 year ago

ajstewart commented 1 year ago

ALL software version info

Description of expected behavior and the observed behavior

While I am using hvplot to plot, after updating to holoviews 1.15.2 one of my plots, a heat map plot with a count aggregation on a object column, failed to process and instead resulted in the error I have included below. This does not happen on 1.15.1.

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

I have created a minimal situation to reproduce the error I am seeing on my plot. Essentially I am generating a heatmap with a count aggregation on a string (object) column of a data frame. In the example below it will always come out to 4 for each cell.

If I change the count from the object column id to the int column value then the plot is created as expected.

import hvplot.pandas  # noqa
import pandas as pd
import random

def gen_df():
    df = pd.DataFrame({
        'month': dates.month,
        'hour': dates.hour,
        'day': dates.day,
        'value': [random.randint(0, 100) for i in range(len(dates))],
    })

    df['id'] = 'test'

    return df

dates = pd.date_range("2022-09-01", "2022-10-31", freq='h')

df = gen_df()

for i in range(3):
    df = pd.concat([df, gen_df()])

df.hvplot.heatmap(x='hour', y='day', C='id', groupby='month', reduce_function='count')

Stack traceback and/or browser JavaScript console output

Traceback (most recent call last):
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/IPython/core/formatters.py", line 222, in catch_format_error
    r = method(self, *args, **kwargs)
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/IPython/core/formatters.py", line 973, in __call__
    return method(include=include, exclude=exclude)
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/holoviews/core/dimension.py", line 1293, in _repr_mimebundle_
    return Store.render(self)
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/holoviews/core/options.py", line 1426, in render
    ret = hook(obj)
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/holoviews/ipython/display_hooks.py", line 277, in pprint_display
    return display(obj, raw_output=True)
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/holoviews/ipython/display_hooks.py", line 253, in display
    output = map_display(obj)
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/holoviews/ipython/display_hooks.py", line 141, in wrapped
    mimebundle = fn(element, max_frames=max_frames)
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/holoviews/ipython/display_hooks.py", line 201, in map_display
    return render(vmap)
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/holoviews/ipython/display_hooks.py", line 68, in render
    return renderer.components(obj, **kwargs)
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/holoviews/plotting/renderer.py", line 398, in components
    return self._render_panel(plot, embed, comm)
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/holoviews/plotting/renderer.py", line 405, in _render_panel
    model = plot.layout._render_model(doc, comm)
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/panel/viewable.py", line 508, in _render_model
    model = self.get_root(doc, comm)
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/panel/viewable.py", line 559, in get_root
    root = self._get_model(doc, comm=comm)
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/panel/layout/base.py", line 146, in _get_model
    objects = self._get_objects(model, [], doc, root, comm)
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/panel/layout/base.py", line 131, in _get_objects
    child = pane._get_model(doc, root, model, comm)
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/panel/pane/holoviews.py", line 265, in _get_model
    plot = self._render(doc, comm, root)
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/panel/pane/holoviews.py", line 342, in _render
    return renderer.get_plot(self.object, **kwargs)
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/holoviews/plotting/bokeh/renderer.py", line 70, in get_plot
    plot = super().get_plot(obj, doc, renderer, **kwargs)
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/holoviews/plotting/renderer.py", line 240, in get_plot
    plot.update(init_key)
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/holoviews/plotting/plot.py", line 948, in update
    return self.initialize_plot()
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/holoviews/plotting/bokeh/element.py", line 1380, in initialize_plot
    ranges = self.compute_ranges(self.hmap, key, ranges)
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/holoviews/plotting/plot.py", line 607, in compute_ranges
    self._compute_group_range(group, elements, ranges, framewise,
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/holoviews/plotting/plot.py", line 717, in _compute_group_range
    data_range = el.range(el_dim, dimension_range=False)
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/holoviews/core/data/__init__.py", line 204, in pipelined_fn
    result = method_fn(*args, **kwargs)
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/holoviews/element/raster.py", line 853, in range
    self.gridded._binned = False
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/holoviews/element/raster.py", line 819, in gridded
    self._gridded = categorical_aggregate2d(self)
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/param/parameterized.py", line 3654, in __new__
    return inst.__call__(*args,**params)
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/holoviews/core/operation.py", line 220, in __call__
    return element.apply(self, **kwargs)
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/holoviews/core/accessors.py", line 45, in pipelined_call
    result = __call__(*args, **kwargs)
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/holoviews/core/accessors.py", line 202, in __call__
    new_obj = apply_function(self._obj, **inner_kwargs)
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/holoviews/core/operation.py", line 214, in __call__
    return self._apply(element)
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/holoviews/core/operation.py", line 141, in _apply
    ret = self._process(element, key)
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/holoviews/element/util.py", line 229, in _process
    raise ValueError("Must have at two dimensions to aggregate over"
ValueError: Must have at two dimensions to aggregate overand one value dimension to aggregate on.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/IPython/core/interactiveshell.py", line 1997, in showtraceback
    stb = self.InteractiveTB.structured_traceback(
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/IPython/core/ultratb.py", line 1112, in structured_traceback
    return FormattedTB.structured_traceback(
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/IPython/core/ultratb.py", line 1006, in structured_traceback
    return VerboseTB.structured_traceback(
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/IPython/core/ultratb.py", line 859, in structured_traceback
    formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/IPython/core/ultratb.py", line 812, in format_exception_as_a_whole
    frames.append(self.format_record(r))
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/IPython/core/ultratb.py", line 730, in format_record
    result += ''.join(_format_traceback_lines(frame_info.lines, Colors, self.has_colors, lvals))
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/stack_data/utils.py", line 145, in cached_property_wrapper
    value = obj.__dict__[self.func.__name__] = self.func(obj)
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/stack_data/core.py", line 734, in lines
    pieces = self.included_pieces
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/stack_data/utils.py", line 145, in cached_property_wrapper
    value = obj.__dict__[self.func.__name__] = self.func(obj)
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/stack_data/core.py", line 677, in included_pieces
    scope_pieces = self.scope_pieces
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/stack_data/utils.py", line 145, in cached_property_wrapper
    value = obj.__dict__[self.func.__name__] = self.func(obj)
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/stack_data/core.py", line 617, in scope_pieces
    for piece in self.source.pieces
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/stack_data/utils.py", line 145, in cached_property_wrapper
    value = obj.__dict__[self.func.__name__] = self.func(obj)
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/stack_data/core.py", line 106, in pieces
    return list(self._clean_pieces())
  File "/Users/adamstewart/miniforge3/envs/light-command-dash/lib/python3.9/site-packages/stack_data/core.py", line 130, in _clean_pieces
    raise AssertionError("Pieces mismatches: %s" % mismatches)
AssertionError: Pieces mismatches: [{680, 681}, {696, 695}, {708, 709}, {714, 715}]

Screenshots or screencasts of the bug in action

Expected output:

Screen Shot 2022-11-04 at 16 26 59
ajstewart commented 1 year ago

Still meeting this issue as of v1.15.3 - would anyone have any insight if this is a bug or am I doing something wrong?