# Buggy code
def _compute_group_range(cls, group, elements, ranges, framewise, top_level):
    # Iterate over all elements in a normalization group
    # and accumulate their ranges into the supplied dictionary.
    elements = [el for el in elements if el is not None]
    prev_ranges = ranges.get(group, {})
    group_ranges = OrderedDict()
    for el in elements:
        if isinstance(el, (Empty, Table)):
            continue
        opts = cls.lookup_options(el, "style")
        plot_opts = cls.lookup_options(el, "plot")

        # Compute normalization for color dim transforms
        for k, v in dict(opts.kwargs, **plot_opts.kwargs).items():
            if not isinstance(v, dim) or ("color" not in k and k != "magnitude"):
                continue

            if isinstance(v, dim) and v.applies(el):
                dim_name = repr(v)
                if dim_name in prev_ranges and not framewise:
                    continue
                values = v.apply(el, expanded=False, all_values=True)
                factors = None
                if values.dtype.kind == "M":
                    drange = values.min(), values.max()
                elif util.isscalar(values):
                    drange = values, values
                elif len(values) == 0:
                    drange = np.NaN, np.NaN
                else:
                    try:
                        with warnings.catch_warnings():
                            warnings.filterwarnings(
                                "ignore", r"All-NaN (slice|axis) encountered"
                            )
                            drange = (np.nanmin(values), np.nanmax(values))
                    except:
                        factors = util.unique_array(values)
                if dim_name not in group_ranges:
                    group_ranges[dim_name] = {"data": [], "hard": [], "soft": []}

                if factors is not None:
                    if "factors" not in group_ranges[dim_name]:
                        group_ranges[dim_name]["factors"] = []
                    group_ranges[dim_name]["factors"].append(factors)
                else:
                    group_ranges[dim_name]["data"].append(drange)

        # Compute dimension normalization
        for el_dim in el.dimensions("ranges"):
            dim_name = el_dim.name
            if dim_name in prev_ranges and not framewise:
                continue
            if hasattr(el, "interface"):
                if isinstance(el, Graph) and el_dim in el.nodes.dimensions():
                    dtype = el.nodes.interface.dtype(el.nodes, el_dim)
                elif isinstance(el, Contours) and el.level is not None:
                    dtype = np.array([el.level]).dtype  # Remove when deprecating level
                else:
                    dtype = el.interface.dtype(el, el_dim)
            else:
                dtype = None

            if all(util.isfinite(r) for r in el_dim.range):
                data_range = (None, None)
            elif dtype is not None and dtype.kind in "SU":
                data_range = ("", "")
            elif isinstance(el, Graph) and el_dim in el.kdims[:2]:
                data_range = el.nodes.range(2, dimension_range=False)
            elif el_dim.values:
                ds = Dataset(el_dim.values, el_dim)
                data_range = ds.range(el_dim, dimension_range=False)
            else:
                data_range = el.range(el_dim, dimension_range=False)

            if dim_name not in group_ranges:
                group_ranges[dim_name] = {"data": [], "hard": [], "soft": []}
            group_ranges[dim_name]["data"].append(data_range)
            group_ranges[dim_name]["hard"].append(el_dim.range)
            group_ranges[dim_name]["soft"].append(el_dim.soft_range)
            if (
                any(isinstance(r, util.basestring) for r in data_range)
                or el_dim.type is not None
                and issubclass(el_dim.type, util.basestring)
            ):
                if "factors" not in group_ranges[dim_name]:
                    group_ranges[dim_name]["factors"] = []
                if el_dim.values not in ([], None):
                    values = el_dim.values
                elif el_dim in el:
                    if isinstance(el, Graph) and el_dim in el.kdims[:2]:
                        # Graph start/end normalization should include all node indices
                        values = el.nodes.dimension_values(2, expanded=False)
                    else:
                        values = el.dimension_values(el_dim, expanded=False)
                elif isinstance(el, Graph) and el_dim in el.nodes:
                    values = el.nodes.dimension_values(el_dim, expanded=False)
                if (
                    isinstance(values, np.ndarray)
                    and values.dtype.kind == "O"
                    and all(isinstance(v, (np.ndarray)) for v in values)
                ):
                    values = np.concatenate(values)
                factors = util.unique_array(values)
                group_ranges[dim_name]["factors"].append(factors)

    group_dim_ranges = defaultdict(dict)
    for gdim, values in group_ranges.items():
        matching = True
        for t, rs in values.items():
            if t == "factors":
                continue
            matching &= (
                len(
                    {
                        "date" if isinstance(v, util.datetime_types) else "number"
                        for rng in rs
                        for v in rng
                        if util.isfinite(v)
                    }
                )
                < 2
            )
        if matching:
            group_dim_ranges[gdim] = values

    dim_ranges = []
    for gdim, values in group_dim_ranges.items():
        hard_range = util.max_range(values["hard"], combined=False)
        soft_range = util.max_range(values["soft"])
        data_range = util.max_range(values["data"])
        combined = util.dimension_range(
            data_range[0], data_range[1], hard_range, soft_range
        )
        dranges = {
            "data": data_range,
            "hard": hard_range,
            "soft": soft_range,
            "combined": combined,
        }
        if "factors" in values:
            dranges["factors"] = util.unique_array(
                [v for fctrs in values["factors"] for v in fctrs]
            )
        dim_ranges.append((gdim, dranges))
    if prev_ranges and not (framewise and top_level):
        for d, dranges in dim_ranges:
            for g, drange in dranges.items():
                prange = prev_ranges.get(d, {}).get(g, None)
                if prange is None:
                    if d not in prev_ranges:
                        prev_ranges[d] = {}
                    prev_ranges[d][g] = drange
                else:
                    prev_ranges[d][g] = util.max_range(
                        [drange, prange], combined=g == "hard"
                    )
    else:
        ranges[group] = OrderedDict(dim_ranges)


# Traceback (KeyError)
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
~/miniconda3/envs/py37/lib/python3.7/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:

~/miniconda3/envs/py37/lib/python3.7/site-packages/holoviews/core/dimension.py in _repr_mimebundle_(self, include, exclude)
1302         combined and returned.
1303         """
-> 1304         return Store.render(self)
1305
1306

~/miniconda3/envs/py37/lib/python3.7/site-packages/holoviews/core/options.py in render(cls, obj)
1393         data, metadata = {}, {}
1394         for hook in hooks:
-> 1395             ret = hook(obj)
1396             if ret is None:
1397                 continue

~/miniconda3/envs/py37/lib/python3.7/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

~/miniconda3/envs/py37/lib/python3.7/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):

~/miniconda3/envs/py37/lib/python3.7/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 {}, {}

~/miniconda3/envs/py37/lib/python3.7/site-packages/holoviews/ipython/display_hooks.py in element_display(element, max_frames)
190         return None
191
--> 192     return render(element)
193
194

~/miniconda3/envs/py37/lib/python3.7/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

~/miniconda3/envs/py37/lib/python3.7/site-packages/holoviews/plotting/renderer.py in components(self, obj, fmt, comm, **kwargs)
353             plot = obj
354         else:
--> 355             plot, fmt = self._validate(obj, fmt)
356
357         data, metadata = {}, {}

~/miniconda3/envs/py37/lib/python3.7/site-packages/holoviews/plotting/renderer.py in _validate(self, obj, fmt, **kwargs)
278                                  renderer=self)
279         else:
--> 280             plot = self.get_plot(obj, renderer=self, **kwargs)
281
282         all_formats = set(fig_formats + holomap_formats)

~/miniconda3/envs/py37/lib/python3.7/site-packages/holoviews/plotting/renderer.py in get_plot(self_or_cls, obj, doc, renderer, comm, **kwargs)
221             init_key = tuple(v if d is None else d for v, d in
222                              zip(plot.keys[0], defaults))
--> 223             plot.update(init_key)
224         else:
225             plot = obj

~/miniconda3/envs/py37/lib/python3.7/site-packages/holoviews/plotting/mpl/plot.py in update(self, key)
257     def update(self, key):
258         if len(self) == 1 and ((key == 0) or (key == self.keys[0])) and not self.drawn:
--> 259             return self.initialize_plot()
260         return self.__getitem__(key)
261

~/miniconda3/envs/py37/lib/python3.7/site-packages/holoviews/plotting/mpl/plot.py in wrapper(self, *args, **kwargs)
53     def wrapper(self, *args, **kwargs):
54         with _rc_context(self.fig_rcparams):
---> 55             return f(self, *args, **kwargs)
56     return wrapper
57

~/miniconda3/envs/py37/lib/python3.7/site-packages/holoviews/plotting/mpl/element.py in initialize_plot(self, ranges)
508             style['label'] = element.label
509
--> 510         plot_data, plot_kwargs, axis_kwargs = self.get_data(element, ranges, style)
511
512         with abbreviated_exception():

~/miniconda3/envs/py37/lib/python3.7/site-packages/holoviews/plotting/mpl/path.py in get_data(self, element, ranges, style)
66         if not (self.color_index or style_mapping):
67             if cdim:
---> 68                 style['array'] = style.pop('c')
69                 style['clim'] = style.pop('vmin', None), style.pop('vmax', None)
70             return (paths,), style, {'dimensions': dims}

KeyError: 'c'

# Fixed code
def _compute_group_range(cls, group, elements, ranges, framewise, top_level):
    # Iterate over all elements in a normalization group
    # and accumulate their ranges into the supplied dictionary.
    elements = [el for el in elements if el is not None]
    prev_ranges = ranges.get(group, {})
    group_ranges = OrderedDict()
    for el in elements:
        if isinstance(el, (Empty, Table)):
            continue
        opts = cls.lookup_options(el, "style")
        plot_opts = cls.lookup_options(el, "plot")

        # Compute normalization for color dim transforms
        for k, v in dict(opts.kwargs, **plot_opts.kwargs).items():
            if not isinstance(v, dim) or ("color" not in k and k != "magnitude"):
                continue

            if isinstance(v, dim) and v.applies(el):
                dim_name = repr(v)
                if dim_name in prev_ranges and not framewise:
                    continue
                values = v.apply(el, all_values=True)
                factors = None
                if values.dtype.kind == "M":
                    drange = values.min(), values.max()
                elif util.isscalar(values):
                    drange = values, values
                elif len(values) == 0:
                    drange = np.NaN, np.NaN
                else:
                    try:
                        with warnings.catch_warnings():
                            warnings.filterwarnings(
                                "ignore", r"All-NaN (slice|axis) encountered"
                            )
                            drange = (np.nanmin(values), np.nanmax(values))
                    except:
                        factors = util.unique_array(values)
                if dim_name not in group_ranges:
                    group_ranges[dim_name] = {"data": [], "hard": [], "soft": []}

                if factors is not None:
                    if "factors" not in group_ranges[dim_name]:
                        group_ranges[dim_name]["factors"] = []
                    group_ranges[dim_name]["factors"].append(factors)
                else:
                    group_ranges[dim_name]["data"].append(drange)

        # Compute dimension normalization
        for el_dim in el.dimensions("ranges"):
            dim_name = el_dim.name
            if dim_name in prev_ranges and not framewise:
                continue
            if hasattr(el, "interface"):
                if isinstance(el, Graph) and el_dim in el.nodes.dimensions():
                    dtype = el.nodes.interface.dtype(el.nodes, el_dim)
                elif isinstance(el, Contours) and el.level is not None:
                    dtype = np.array([el.level]).dtype  # Remove when deprecating level
                else:
                    dtype = el.interface.dtype(el, el_dim)
            else:
                dtype = None

            if all(util.isfinite(r) for r in el_dim.range):
                data_range = (None, None)
            elif dtype is not None and dtype.kind in "SU":
                data_range = ("", "")
            elif isinstance(el, Graph) and el_dim in el.kdims[:2]:
                data_range = el.nodes.range(2, dimension_range=False)
            elif el_dim.values:
                ds = Dataset(el_dim.values, el_dim)
                data_range = ds.range(el_dim, dimension_range=False)
            else:
                data_range = el.range(el_dim, dimension_range=False)

            if dim_name not in group_ranges:
                group_ranges[dim_name] = {"data": [], "hard": [], "soft": []}
            group_ranges[dim_name]["data"].append(data_range)
            group_ranges[dim_name]["hard"].append(el_dim.range)
            group_ranges[dim_name]["soft"].append(el_dim.soft_range)
            if (
                any(isinstance(r, util.basestring) for r in data_range)
                or el_dim.type is not None
                and issubclass(el_dim.type, util.basestring)
            ):
                if "factors" not in group_ranges[dim_name]:
                    group_ranges[dim_name]["factors"] = []
                if el_dim.values not in ([], None):
                    values = el_dim.values
                elif el_dim in el:
                    if isinstance(el, Graph) and el_dim in el.kdims[:2]:
                        # Graph start/end normalization should include all node indices
                        values = el.nodes.dimension_values(2, expanded=False)
                    else:
                        values = el.dimension_values(el_dim, expanded=False)
                elif isinstance(el, Graph) and el_dim in el.nodes:
                    values = el.nodes.dimension_values(el_dim, expanded=False)
                if (
                    isinstance(values, np.ndarray)
                    and values.dtype.kind == "O"
                    and all(isinstance(v, (np.ndarray)) for v in values)
                ):
                    values = np.concatenate(values)
                factors = util.unique_array(values)
                group_ranges[dim_name]["factors"].append(factors)

    group_dim_ranges = defaultdict(dict)
    for gdim, values in group_ranges.items():
        matching = True
        for t, rs in values.items():
            if t == "factors":
                continue
            matching &= (
                len(
                    {
                        "date" if isinstance(v, util.datetime_types) else "number"
                        for rng in rs
                        for v in rng
                        if util.isfinite(v)
                    }
                )
                < 2
            )
        if matching:
            group_dim_ranges[gdim] = values

    dim_ranges = []
    for gdim, values in group_dim_ranges.items():
        hard_range = util.max_range(values["hard"], combined=False)
        soft_range = util.max_range(values["soft"])
        data_range = util.max_range(values["data"])
        combined = util.dimension_range(
            data_range[0], data_range[1], hard_range, soft_range
        )
        dranges = {
            "data": data_range,
            "hard": hard_range,
            "soft": soft_range,
            "combined": combined,
        }
        if "factors" in values:
            dranges["factors"] = util.unique_array(
                [v for fctrs in values["factors"] for v in fctrs]
            )
        dim_ranges.append((gdim, dranges))
    if prev_ranges and not (framewise and top_level):
        for d, dranges in dim_ranges:
            for g, drange in dranges.items():
                prange = prev_ranges.get(d, {}).get(g, None)
                if prange is None:
                    if d not in prev_ranges:
                        prev_ranges[d] = {}
                    prev_ranges[d][g] = drange
                else:
                    prev_ranges[d][g] = util.max_range(
                        [drange, prange], combined=g == "hard"
                    )
    else:
        ranges[group] = OrderedDict(dim_ranges)