From 508d0d204ea5151cd64756425611a2c26e5365b3 Mon Sep 17 00:00:00 2001 From: mzeitlin11 <37011898+mzeitlin11@users.noreply.github.com> Date: Tue, 29 Dec 2020 14:51:23 -0500 Subject: [PATCH] BUG: Ensure series/frame mode() keeps int index (#38732) --- doc/source/whatsnew/v1.3.0.rst | 1 + pandas/core/algorithms.py | 4 +++- pandas/core/frame.py | 7 ++++++- pandas/tests/frame/test_reductions.py | 6 ++++++ pandas/tests/test_algos.py | 2 +- 5 files changed, 17 insertions(+), 3 deletions(-) diff --git a/doc/source/whatsnew/v1.3.0.rst b/doc/source/whatsnew/v1.3.0.rst index ca9b285ef6692..83bff6d7bfb2d 100644 --- a/doc/source/whatsnew/v1.3.0.rst +++ b/doc/source/whatsnew/v1.3.0.rst @@ -210,6 +210,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):