From 74f5f03e10720d0172ff7b8d42548918b4441737 Mon Sep 17 00:00:00 2001 From: Arno Veenstra Date: Fri, 15 Feb 2019 10:27:59 +0100 Subject: [PATCH 1/4] Make sure numeric_only works for Categorical --- doc/source/whatsnew/v0.24.2.rst | 1 + pandas/core/arrays/categorical.py | 2 +- pandas/core/series.py | 8 ++++++-- pandas/tests/reductions/test_reductions.py | 12 ++++++++++++ 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/doc/source/whatsnew/v0.24.2.rst b/doc/source/whatsnew/v0.24.2.rst index f17c4974cd450..8edc9820f5d07 100644 --- a/doc/source/whatsnew/v0.24.2.rst +++ b/doc/source/whatsnew/v0.24.2.rst @@ -25,6 +25,7 @@ Fixed Regressions - Fixed regression in :meth:`DataFrame.apply` causing ``RecursionError`` when ``dict``-like classes were passed as argument. (:issue:`25196`) - Fixed regression in :meth:`DataFrame.duplicated()`, where empty dataframe was not returning a boolean dtyped Series. (:issue:`25184`) +- Fixed regression in :meth:`Categorical.min` and :meth:`Categorical.max` where ``numeric_only=True`` was ignored (:issue:`25299`) .. _whatsnew_0242.enhancements: diff --git a/pandas/core/arrays/categorical.py b/pandas/core/arrays/categorical.py index d7d0882bbcc94..6b977e34ae7f8 100644 --- a/pandas/core/arrays/categorical.py +++ b/pandas/core/arrays/categorical.py @@ -2172,7 +2172,7 @@ def _reverse_indexer(self): return result # reduction ops # - def _reduce(self, name, axis=0, skipna=True, **kwargs): + def _reduce(self, name, axis=0, **kwargs): func = getattr(self, name, None) if func is None: msg = 'Categorical cannot perform the operation {op}' diff --git a/pandas/core/series.py b/pandas/core/series.py index 31c6247436418..e18383372e54c 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -3678,8 +3678,12 @@ def _reduce(self, op, name, axis=0, skipna=True, numeric_only=None, if axis is not None: self._get_axis_number(axis) - # dispatch to ExtensionArray interface - if isinstance(delegate, ExtensionArray): + if isinstance(delegate, Categorical): + # TODO deprecate numeric_only argument for Categorical and use + # skipna as well + return delegate._reduce(name, numeric_only=numeric_only, **kwds) + elif isinstance(delegate, ExtensionArray): + # dispatch to ExtensionArray interface return delegate._reduce(name, skipna=skipna, **kwds) elif is_datetime64_dtype(delegate): # use DatetimeIndex implementation to handle skipna correctly diff --git a/pandas/tests/reductions/test_reductions.py b/pandas/tests/reductions/test_reductions.py index 173f719edd465..4c65a5fa994bc 100644 --- a/pandas/tests/reductions/test_reductions.py +++ b/pandas/tests/reductions/test_reductions.py @@ -960,6 +960,18 @@ def test_min_max(self): assert np.isnan(_min) assert _max == 1 + cat = Series(Categorical( + ["a", "b", np.nan, "a"], categories=['b', 'a'], ordered=True)) + _min = cat.min(numeric_only=True) + _max = cat.max(numeric_only=True) + assert _min == "b" + assert _max == "a" + + _min = cat.min(numeric_only=False) + _max = cat.max(numeric_only=False) + assert np.isnan(_min) + assert _max == "a" + class TestSeriesMode(object): # Note: the name TestSeriesMode indicates these tests From 36b34bdad7639499fca27b1221b3238189428202 Mon Sep 17 00:00:00 2001 From: Arno Veenstra Date: Fri, 15 Feb 2019 11:27:52 +0100 Subject: [PATCH 2/4] Update comment and whatsnew --- doc/source/whatsnew/v0.24.2.rst | 2 +- pandas/core/series.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/source/whatsnew/v0.24.2.rst b/doc/source/whatsnew/v0.24.2.rst index 8edc9820f5d07..f9b19e18d56d8 100644 --- a/doc/source/whatsnew/v0.24.2.rst +++ b/doc/source/whatsnew/v0.24.2.rst @@ -25,7 +25,7 @@ Fixed Regressions - Fixed regression in :meth:`DataFrame.apply` causing ``RecursionError`` when ``dict``-like classes were passed as argument. (:issue:`25196`) - Fixed regression in :meth:`DataFrame.duplicated()`, where empty dataframe was not returning a boolean dtyped Series. (:issue:`25184`) -- Fixed regression in :meth:`Categorical.min` and :meth:`Categorical.max` where ``numeric_only=True`` was ignored (:issue:`25299`) +- Fixed regression in :meth:`Series.min` and :meth:`Series.max` where ``numeric_only=True`` was ignored when the `Series` contained `Categorical` data (:issue:`25299`) .. _whatsnew_0242.enhancements: diff --git a/pandas/core/series.py b/pandas/core/series.py index e18383372e54c..a5dfe8d43c336 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -3680,7 +3680,7 @@ def _reduce(self, op, name, axis=0, skipna=True, numeric_only=None, if isinstance(delegate, Categorical): # TODO deprecate numeric_only argument for Categorical and use - # skipna as well + # skipna as well, see GH25303 return delegate._reduce(name, numeric_only=numeric_only, **kwds) elif isinstance(delegate, ExtensionArray): # dispatch to ExtensionArray interface From 4b6d9a47525ce693af874dd6ee674b16f6ac5d11 Mon Sep 17 00:00:00 2001 From: Arno Veenstra Date: Fri, 15 Feb 2019 11:35:43 +0100 Subject: [PATCH 3/4] Fix backticks --- doc/source/whatsnew/v0.24.2.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v0.24.2.rst b/doc/source/whatsnew/v0.24.2.rst index f9b19e18d56d8..089da5f13c73f 100644 --- a/doc/source/whatsnew/v0.24.2.rst +++ b/doc/source/whatsnew/v0.24.2.rst @@ -25,7 +25,7 @@ Fixed Regressions - Fixed regression in :meth:`DataFrame.apply` causing ``RecursionError`` when ``dict``-like classes were passed as argument. (:issue:`25196`) - Fixed regression in :meth:`DataFrame.duplicated()`, where empty dataframe was not returning a boolean dtyped Series. (:issue:`25184`) -- Fixed regression in :meth:`Series.min` and :meth:`Series.max` where ``numeric_only=True`` was ignored when the `Series` contained `Categorical` data (:issue:`25299`) +- Fixed regression in :meth:`Series.min` and :meth:`Series.max` where ``numeric_only=True`` was ignored when the ``Series`` contained ```Categorical`` data (:issue:`25299`) .. _whatsnew_0242.enhancements: From ec1fa9f5cab13e4378746a4654262594597e250c Mon Sep 17 00:00:00 2001 From: Arno Veenstra Date: Fri, 15 Feb 2019 13:31:52 +0100 Subject: [PATCH 4/4] Use separate test name and add comment. --- pandas/tests/reductions/test_reductions.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pandas/tests/reductions/test_reductions.py b/pandas/tests/reductions/test_reductions.py index 4c65a5fa994bc..8520855d14918 100644 --- a/pandas/tests/reductions/test_reductions.py +++ b/pandas/tests/reductions/test_reductions.py @@ -960,8 +960,17 @@ def test_min_max(self): assert np.isnan(_min) assert _max == 1 + def test_min_max_numeric_only(self): + # TODO deprecate numeric_only argument for Categorical and use + # skipna as well, see GH25303 cat = Series(Categorical( ["a", "b", np.nan, "a"], categories=['b', 'a'], ordered=True)) + + _min = cat.min() + _max = cat.max() + assert np.isnan(_min) + assert _max == "a" + _min = cat.min(numeric_only=True) _max = cat.max(numeric_only=True) assert _min == "b"