# Buggy code
def explode(self):
    """
    Explode muti-part geometries into multiple single geometries.

    Each row containing a multi-part geometry will be split into
    multiple rows with single geometries, thereby increasing the vertical
    size of the GeoDataFrame.

    The index of the input geodataframe is no longer unique and is
    replaced with a multi-index (original index with additional level
    indicating the multiple geometries: a new zero-based index for each
    single part geometry per multi-part geometry).

    Returns
    -------
    GeoDataFrame
        Exploded geodataframe with each single geometry
        as a separate entry in the geodataframe.

    """
    df_copy = self.copy()

    exploded_geom = df_copy.geometry.explode().reset_index(level=-1)
    exploded_index = exploded_geom.columns[0]

    df = pd.concat(
        [df_copy.drop(df_copy._geometry_column_name, axis=1), exploded_geom], axis=1
    )
    # reset to MultiIndex, otherwise df index is only first level of
    # exploded GeoSeries index.
    df.set_index(exploded_index, append=True, inplace=True)
    df.index.names = list(self.index.names) + [None]
    geo_df = df.set_geometry(self._geometry_column_name)
    return geo_df


# Traceback (ValueError)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
~/anaconda3/envs/uap/lib/python3.8/site-packages/pandas/core/arrays/categorical.py in __init__(self, values, categories, ordered, dtype, fastpath)
354             try:
--> 355                 codes, categories = factorize(values, sort=True)
356             except TypeError:

~/anaconda3/envs/uap/lib/python3.8/site-packages/pandas/core/algorithms.py in factorize(values, sort, na_sentinel, size_hint)
634
--> 635         codes, uniques = _factorize_array(
636             values, na_sentinel=na_sentinel, size_hint=size_hint, na_value=na_value

~/anaconda3/envs/uap/lib/python3.8/site-packages/pandas/core/algorithms.py in _factorize_array(values, na_sentinel, size_hint, na_value)
483     table = hash_klass(size_hint or len(values))
--> 484     uniques, codes = table.factorize(values, na_sentinel=na_sentinel, na_value=na_value)
485

pandas/_libs/hashtable_class_helper.pxi in pandas._libs.hashtable.Int64HashTable.factorize()

ValueError: Buffer has wrong number of dimensions (expected 1, got 2)

During handling of the above exception, another exception occurred:

NotImplementedError                       Traceback (most recent call last)
<ipython-input-66-973d8edd5e42> in <module>
----> 1 gdf.explode()

~/Dropbox/Python/geopandas/geopandas/geopandas/geodataframe.py in explode(self)
844         # reset to MultiIndex, otherwise df index is only first level of
845         # exploded GeoSeries index.
--> 846         df.set_index(exploded_index, append=True, inplace=True)
847         df.index.names = list(self.index.names) + [None]
848         geo_df = df.set_geometry(self._geometry_column_name)

~/anaconda3/envs/uap/lib/python3.8/site-packages/pandas/core/frame.py in set_index(self, keys, drop, append, inplace, verify_integrity)
4349                 )
4350
-> 4351         index = ensure_index_from_sequences(arrays, names)
4352
4353         if verify_integrity and not index.is_unique:

~/anaconda3/envs/uap/lib/python3.8/site-packages/pandas/core/indexes/base.py in ensure_index_from_sequences(sequences, names)
5288         return Index(sequences[0], name=names)
5289     else:
-> 5290         return MultiIndex.from_arrays(sequences, names=names)
5291
5292

~/anaconda3/envs/uap/lib/python3.8/site-packages/pandas/core/indexes/multi.py in from_arrays(cls, arrays, sortorder, names)
425                 raise ValueError("all arrays must be same length")
426
--> 427         codes, levels = factorize_from_iterables(arrays)
428         if names is lib.no_default:
429             names = [getattr(arr, "name", None) for arr in arrays]

~/anaconda3/envs/uap/lib/python3.8/site-packages/pandas/core/arrays/categorical.py in factorize_from_iterables(iterables)
2706         # For consistency, it should return a list of 2 lists.
2707         return [[], []]
-> 2708     return map(list, zip(*(factorize_from_iterable(it) for it in iterables)))

~/anaconda3/envs/uap/lib/python3.8/site-packages/pandas/core/arrays/categorical.py in <genexpr>(.0)
2706         # For consistency, it should return a list of 2 lists.
2707         return [[], []]
-> 2708     return map(list, zip(*(factorize_from_iterable(it) for it in iterables)))

~/anaconda3/envs/uap/lib/python3.8/site-packages/pandas/core/arrays/categorical.py in factorize_from_iterable(values)
2678         # but only the resulting categories, the order of which is independent
2679         # from ordered. Set ordered to False as default. See GH #15457
-> 2680         cat = Categorical(values, ordered=False)
2681         categories = cat.categories
2682         codes = cat.codes

~/anaconda3/envs/uap/lib/python3.8/site-packages/pandas/core/arrays/categorical.py in __init__(self, values, categories, ordered, dtype, fastpath)
367
368                 # FIXME
--> 369                 raise NotImplementedError(
370                     "> 1 ndim Categorical are not supported at this time"
371                 )

NotImplementedError: > 1 ndim Categorical are not supported at this time

# Fixed code
def explode(self):
    """
    Explode muti-part geometries into multiple single geometries.

    Each row containing a multi-part geometry will be split into
    multiple rows with single geometries, thereby increasing the vertical
    size of the GeoDataFrame.

    The index of the input geodataframe is no longer unique and is
    replaced with a multi-index (original index with additional level
    indicating the multiple geometries: a new zero-based index for each
    single part geometry per multi-part geometry).

    Returns
    -------
    GeoDataFrame
        Exploded geodataframe with each single geometry
        as a separate entry in the geodataframe.

    """
    df_copy = self.copy()

    if "level_1" in df_copy.columns:  # GH1393
        df_copy = df_copy.rename(columns={"level_1": "__level_1"})

    exploded_geom = df_copy.geometry.explode().reset_index(level=-1)
    exploded_index = exploded_geom.columns[0]

    df = pd.concat(
        [df_copy.drop(df_copy._geometry_column_name, axis=1), exploded_geom], axis=1
    )
    # reset to MultiIndex, otherwise df index is only first level of
    # exploded GeoSeries index.
    df.set_index(exploded_index, append=True, inplace=True)
    df.index.names = list(self.index.names) + [None]

    if "__level_1" in df.columns:
        df = df.rename(columns={"__level_1": "level_1"})

    geo_df = df.set_geometry(self._geometry_column_name)
    return geo_df