diff --git a/doc/source/whatsnew/v1.3.0.rst b/doc/source/whatsnew/v1.3.0.rst index 77bc080892e6c..d9ee3033b04b9 100644 --- a/doc/source/whatsnew/v1.3.0.rst +++ b/doc/source/whatsnew/v1.3.0.rst @@ -208,6 +208,7 @@ Numeric ^^^^^^^ - Bug in :meth:`DataFrame.quantile`, :meth:`DataFrame.sort_values` causing incorrect subsequent indexing behavior (:issue:`38351`) - Bug in :meth:`DataFrame.select_dtypes` with ``include=np.number`` now retains numeric ``ExtensionDtype`` columns (:issue:`35340`) +- Bug in :meth:`DataFrame.mode` and :meth:`Series.mode` not keeping consistent integer :class:`Index` for empty input (:issue:`33321`) Conversion ^^^^^^^^^^ diff --git a/pandas/core/algorithms.py b/pandas/core/algorithms.py index 2098392cf70a9..5e74db41b8740 100644 --- a/pandas/core/algorithms.py +++ b/pandas/core/algorithms.py @@ -928,6 +928,7 @@ def mode(values, dropna: bool = True) -> Series: mode : Series """ from pandas import Series + import pandas.core.indexes.base as ibase values = _ensure_arraylike(values) original = values @@ -954,7 +955,8 @@ def mode(values, dropna: bool = True) -> Series: warn(f"Unable to sort modes: {err}") result = _reconstruct_data(result, original.dtype, original) - return Series(result) + # Ensure index is type stable (should always use int index) + return Series(result, index=ibase.default_index(len(result))) def rank( diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 42b3046b0ffe9..7f295a73a82e6 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -9230,7 +9230,12 @@ def mode( def f(s): return s.mode(dropna=dropna) - return data.apply(f, axis=axis) + data = data.apply(f, axis=axis) + # Ensure index is type stable (should always use int index) + if data.empty: + data.index = ibase.default_index(0) + + return data def quantile( self, diff --git a/pandas/tests/frame/test_reductions.py b/pandas/tests/frame/test_reductions.py index d33d91f2cefca..f6313fc806305 100644 --- a/pandas/tests/frame/test_reductions.py +++ b/pandas/tests/frame/test_reductions.py @@ -669,6 +669,12 @@ def test_mode_sortwarning(self): tm.assert_frame_equal(result, expected) + def test_mode_empty_df(self): + df = DataFrame([], columns=["a", "b"]) + result = df.mode() + expected = DataFrame([], columns=["a", "b"], index=Index([], dtype=int)) + tm.assert_frame_equal(result, expected) + def test_operators_timedelta64(self): df = DataFrame( { diff --git a/pandas/tests/test_algos.py b/pandas/tests/test_algos.py index 8fcc241348f27..ebaf69e08ccff 100644 --- a/pandas/tests/test_algos.py +++ b/pandas/tests/test_algos.py @@ -2253,7 +2253,7 @@ def test_int64_add_overflow(): class TestMode: def test_no_mode(self): - exp = Series([], dtype=np.float64) + exp = Series([], dtype=np.float64, index=Index([], dtype=int)) tm.assert_series_equal(algos.mode([]), exp) def test_mode_single(self):