# Buggy code
def histogram(
    srs: dd.Series,
    bins: Optional[int] = None,
    return_edges: bool = True,
    range: Optional[Tuple[int, int]] = None,  # pylint: disable=redefined-builtin
    dtype: Optional[DTypeDef] = None,
) -> Union[Tuple[da.Array, da.Array], Tuple[da.Array, da.Array, da.Array]]:
    """
    Calculate histogram for both numerical and categorical
    """

    if is_dtype(detect_dtype(srs, dtype), Continuous()):
        if range is not None:
            minimum, maximum = range
        else:
            minimum, maximum = srs.min(axis=0), srs.max(axis=0)
        minimum, maximum = dask.compute(minimum, maximum)

        assert bins is not None, (
            "num_bins cannot be None if calculating numerical histograms"
        )

        counts, edges = da.histogram(
            srs.to_dask_array(), bins, range=[minimum, maximum]
        )
        centers = (edges[:-1] + edges[1:]) / 2

        if not return_edges:
            return counts, centers
        return counts, centers, edges
    elif is_dtype(detect_dtype(srs, dtype), Nominal()):
        value_counts = srs.value_counts()
        counts = value_counts.to_dask_array()

        # Dask array dones't understand the pandas dtypes such as categorical type.
        # We convert these types into str before calling into `to_dask_array`.

        if is_pandas_categorical(value_counts.index.dtype):
            centers = value_counts.index.astype("str").to_dask_array()
        else:
            centers = value_counts.index.to_dask_array()
        return (counts, centers)
    else:
        raise UnreachableError()


# Traceback (IndexError)
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-50-47c276e219b8> in <module>
----> 1 plot_missing(X)

~\miniconda3\lib\site-packages\dataprep\eda\missing\__init__.py in plot_missing(df, x, y, bins, ncols, ndist_sample, dtype)
63         df, x, y, dtype=dtype, bins=bins, ncols=ncols, ndist_sample=ndist_sample
64     )
---> 65     fig = render_missing(itmdt)
66     return Report(fig)

~\miniconda3\lib\site-packages\dataprep\eda\missing\render.py in render_missing(itmdt, plot_width, plot_height, palette)
61     elif itmdt.visual_type == "missing_spectrum_heatmap":
62         return render_missing_heatmap(
---> 63             itmdt, plot_width, plot_height, palette or BIPALETTE
64         )
65

~\miniconda3\lib\site-packages\dataprep\eda\missing\render.py in render_missing_heatmap(itmdt, plot_width, plot_height, palette)
287     pan_spectrum = Panel(child=fig_spectrum, title="Spectrum")
288     tabs.append(pan_spectrum)
--> 289     fig_heatmap = render_heatmaps_tab(itmdt, plot_width, plot_height, palette)
290     pan_heatmap = Panel(child=fig_heatmap, title="Heatmap")
291     tabs.append(pan_heatmap)

~\miniconda3\lib\site-packages\dataprep\eda\missing\render.py in render_heatmaps_tab(itmdt, plot_width, plot_height, palette)
307         np.triu(np.ones(df.shape)).astype(np.bool)  # pylint: disable=no-member
308     ).T
--> 309     df = df.unstack().reset_index(name="correlation")
310     df = df.rename(columns={"level_0": "x", "level_1": "y"})
311     df = df[df["x"] != df["y"]]

~\miniconda3\lib\site-packages\pandas\core\frame.py in unstack(self, level, fill_value)
6384         from pandas.core.reshape.reshape import unstack
6385
-> 6386         return unstack(self, level, fill_value)
6387
6388     _shared_docs[

~\miniconda3\lib\site-packages\pandas\core\reshape\reshape.py in unstack(obj, level, fill_value)
408             return _unstack_frame(obj, level, fill_value=fill_value)
409         else:
--> 410             return obj.T.stack(dropna=False)
411     else:
412         if is_extension_array_dtype(obj.dtype):

~\miniconda3\lib\site-packages\pandas\core\frame.py in stack(self, level, dropna)
6249             return stack_multiple(self, level, dropna=dropna)
6250         else:
-> 6251             return stack(self, level, dropna=dropna)
6252
6253     def explode(self, column: Union[str, Tuple]) -> "DataFrame":

~\miniconda3\lib\site-packages\pandas\core\reshape\reshape.py in stack(frame, level, dropna)
541         # we concatenate instead.
542         dtypes = list(frame.dtypes.values)
--> 543         dtype = dtypes[0]
544
545         if is_extension_array_dtype(dtype):

IndexError: list index out of range

# Fixed code
def histogram(
    srs: dd.Series,
    bins: Optional[int] = None,
    return_edges: bool = True,
    range: Optional[Tuple[int, int]] = None,  # pylint: disable=redefined-builtin
    dtype: Optional[DTypeDef] = None,
) -> Union[Tuple[da.Array, da.Array], Tuple[da.Array, da.Array, da.Array]]:
    """
    Calculate "histogram" for both numerical and categorical
    """

    if is_dtype(detect_dtype(srs, dtype), Continuous()):
        if range is not None:
            minimum, maximum = range
        else:
            minimum, maximum = srs.min(axis=0), srs.max(axis=0)
        minimum, maximum = dask.compute(minimum, maximum)

        assert bins is not None, (
            "num_bins cannot be None if calculating numerical histograms"
        )

        counts, edges = da.histogram(
            srs.to_dask_array(), bins, range=[minimum, maximum]
        )
        centers = (edges[:-1] + edges[1:]) / 2

        if not return_edges:
            return counts, centers
        return counts, centers, edges
    elif is_dtype(detect_dtype(srs, dtype), Nominal()):
        value_counts = srs.value_counts()
        counts = value_counts.to_dask_array()

        # Dask array dones't understand the pandas dtypes such as categorical type.
        # We convert these types into str before calling into `to_dask_array`.

        if is_pandas_categorical(value_counts.index.dtype):
            centers = value_counts.index.astype("str").to_dask_array()
        else:
            centers = value_counts.index.to_dask_array()
        return (counts, centers)
    else:
        raise UnreachableError()