From 781fa90e4a2d6b9b40de487d7d8ac4194e5342b5 Mon Sep 17 00:00:00 2001 From: richard Date: Fri, 9 Feb 2024 20:58:05 -0500 Subject: [PATCH] CLN: Enforce deprecation of Series.agg using Series.apply --- doc/source/whatsnew/v3.0.0.rst | 1 + pandas/core/apply.py | 17 +------- pandas/tests/apply/test_frame_apply.py | 8 +--- pandas/tests/apply/test_series_apply.py | 53 +++++++++---------------- 4 files changed, 22 insertions(+), 57 deletions(-) diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index 17120f30c21f2..2335c48632252 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -119,6 +119,7 @@ Removal of prior version deprecations/changes - Removed ``pandas.value_counts``, use :meth:`Series.value_counts` instead (:issue:`53493`) - Removed ``read_gbq`` and ``DataFrame.to_gbq``. Use ``pandas_gbq.read_gbq`` and ``pandas_gbq.to_gbq`` instead https://pandas-gbq.readthedocs.io/en/latest/api.html (:issue:`55525`) - Removed deprecated argument ``obj`` in :meth:`.DataFrameGroupBy.get_group` and :meth:`.SeriesGroupBy.get_group` (:issue:`53545`) +- Removed deprecated behavior of :meth:`Series.agg` using :meth:`Series.apply` (:issue:`53325`) - Removed the ``ArrayManager`` (:issue:`55043`) - Removed the ``fastpath`` argument from the :class:`Series` constructor (:issue:`55466`) - Removed the ``is_boolean``, ``is_integer``, ``is_floating``, ``holds_integer``, ``is_numeric``, ``is_categorical``, ``is_object``, and ``is_interval`` attributes of :class:`Index` (:issue:`50042`) diff --git a/pandas/core/apply.py b/pandas/core/apply.py index c15d7b7928867..6265faade2281 100644 --- a/pandas/core/apply.py +++ b/pandas/core/apply.py @@ -1430,22 +1430,7 @@ def agg(self): func = self.func # string, list-like, and dict-like are entirely handled in super assert callable(func) - - # GH53325: The setup below is just to keep current behavior while emitting a - # deprecation message. In the future this will all be replaced with a simple - # `result = f(self.obj, *self.args, **self.kwargs)`. - try: - result = obj.apply(func, args=self.args, **self.kwargs) - except (ValueError, AttributeError, TypeError): - result = func(obj, *self.args, **self.kwargs) - else: - msg = ( - f"using {func} in {type(obj).__name__}.agg cannot aggregate and " - f"has been deprecated. Use {type(obj).__name__}.transform to " - f"keep behavior unchanged." - ) - warnings.warn(msg, FutureWarning, stacklevel=find_stack_level()) - + result = func(obj, *self.args, **self.kwargs) return result def apply_empty_result(self) -> Series: diff --git a/pandas/tests/apply/test_frame_apply.py b/pandas/tests/apply/test_frame_apply.py index c35f9bf13200f..531045b16fee0 100644 --- a/pandas/tests/apply/test_frame_apply.py +++ b/pandas/tests/apply/test_frame_apply.py @@ -1688,18 +1688,14 @@ def foo2(x, b=2, c=0): expected = df + 7 tm.assert_frame_equal(result, expected) - msg = "using .+ in Series.agg cannot aggregate and" - - with tm.assert_produces_warning(FutureWarning, match=msg): - result = df.agg([foo1, foo2], 0, 3, c=4) + result = df.agg([foo1, foo2], 0, 3, c=4) expected = DataFrame( [[8, 8], [9, 9], [10, 10]], columns=[["x", "x"], ["foo1", "foo2"]] ) tm.assert_frame_equal(result, expected) # TODO: the result below is wrong, should be fixed (GH53325) - with tm.assert_produces_warning(FutureWarning, match=msg): - result = df.agg({"x": foo1}, 0, 3, c=4) + result = df.agg({"x": foo1}, 0, 3, c=4) expected = DataFrame([2, 3, 4], columns=["x"]) tm.assert_frame_equal(result, expected) diff --git a/pandas/tests/apply/test_series_apply.py b/pandas/tests/apply/test_series_apply.py index df24fa08f48e1..1e41e54bff6fc 100644 --- a/pandas/tests/apply/test_series_apply.py +++ b/pandas/tests/apply/test_series_apply.py @@ -104,12 +104,7 @@ def f(x, a=0, b=0, c=0): return x + a + 10 * b + 100 * c s = Series([1, 2]) - msg = ( - "in Series.agg cannot aggregate and has been deprecated. " - "Use Series.transform to keep behavior unchanged." - ) - with tm.assert_produces_warning(FutureWarning, match=msg): - result = s.agg(f, 0, *args, **kwargs) + result = s.agg(f, 0, *args, **kwargs) expected = s + increment tm.assert_series_equal(result, expected) @@ -124,13 +119,9 @@ def foo1(x, a=1, c=0): def foo2(x, b=2, c=0): return x + b + c - msg = "using .+ in Series.agg cannot aggregate and" - with tm.assert_produces_warning(FutureWarning, match=msg): - s.agg(foo1, 0, 3, c=4) - with tm.assert_produces_warning(FutureWarning, match=msg): - s.agg([foo1, foo2], 0, 3, c=4) - with tm.assert_produces_warning(FutureWarning, match=msg): - s.agg({"a": foo1, "b": foo2}, 0, 3, c=4) + s.agg(foo1, 0, 3, c=4) + s.agg([foo1, foo2], 0, 3, c=4) + s.agg({"a": foo1, "b": foo2}, 0, 3, c=4) def test_series_apply_map_box_timestamps(by_row): @@ -410,34 +401,26 @@ def test_apply_map_evaluate_lambdas_the_same(string_series, func, by_row): def test_agg_evaluate_lambdas(string_series): # GH53325 - # in the future, the result will be a Series class. - - with tm.assert_produces_warning(FutureWarning): - result = string_series.agg(lambda x: type(x)) - assert isinstance(result, Series) and len(result) == len(string_series) + result = string_series.agg(lambda x: type(x)) + assert result is Series - with tm.assert_produces_warning(FutureWarning): - result = string_series.agg(type) - assert isinstance(result, Series) and len(result) == len(string_series) + result = string_series.agg(type) + assert result is Series @pytest.mark.parametrize("op_name", ["agg", "apply"]) def test_with_nested_series(datetime_series, op_name): - # GH 2316 + # GH 2316 & GH52123 # .agg with a reducer and a transform, what to do - msg = "cannot aggregate" - warning = FutureWarning if op_name == "agg" else None - with tm.assert_produces_warning(warning, match=msg): - # GH52123 - result = getattr(datetime_series, op_name)( - lambda x: Series([x, x**2], index=["x", "x^2"]) - ) - expected = DataFrame({"x": datetime_series, "x^2": datetime_series**2}) - tm.assert_frame_equal(result, expected) - - with tm.assert_produces_warning(FutureWarning, match=msg): - result = datetime_series.agg(lambda x: Series([x, x**2], index=["x", "x^2"])) - tm.assert_frame_equal(result, expected) + result = getattr(datetime_series, op_name)( + lambda x: Series([x, x**2], index=["x", "x^2"]) + ) + if op_name == "apply": + expected = DataFrame({"x": datetime_series, "x^2": datetime_series**2}) + tm.assert_frame_equal(result, expected) + else: + expected = Series([datetime_series, datetime_series**2], index=["x", "x^2"]) + tm.assert_series_equal(result, expected) def test_replicate_describe(string_series):