diff --git a/pandas/core/apply.py b/pandas/core/apply.py index b0f357a1d8db3..c03f1a268906e 100644 --- a/pandas/core/apply.py +++ b/pandas/core/apply.py @@ -91,6 +91,9 @@ def frame_apply( elif axis == 1: klass = FrameColumnApply + _, func, _, _ = reconstruct_func(func, **kwargs) + assert func is not None + return klass( obj, func, @@ -547,7 +550,20 @@ def apply_multiple(self) -> DataFrame | Series: result: Series, DataFrame, or None Result when self.f is a list-like or dict-like, None otherwise. """ - return self.obj.aggregate(self.f, self.axis, *self.args, **self.kwargs) + if self.axis == 1 and isinstance(self.obj, ABCDataFrame): + return self.obj.T.apply(self.f, 0, args=self.args, **self.kwargs).T + + func = self.f + kwargs = self.kwargs + + if is_dict_like(func): + result = self.agg_dict_like() + else: + result = self.agg_list_like() + + result = reconstruct_and_relabel_result(result, func, **kwargs) + + return result def normalize_dictlike_arg( self, how: str, obj: DataFrame | Series, func: AggFuncTypeDict @@ -1439,6 +1455,26 @@ def relabel_result( return reordered_result_in_dict +def reconstruct_and_relabel_result(result, func, **kwargs) -> DataFrame | Series: + from pandas import DataFrame + + relabeling, func, columns, order = reconstruct_func(func, **kwargs) + + if relabeling: + # This is to keep the order to columns occurrence unchanged, and also + # keep the order of new columns occurrence unchanged + + # For the return values of reconstruct_func, if relabeling is + # False, columns and order will be None. + assert columns is not None + assert order is not None + + result_in_dict = relabel_result(result, func, columns, order) + result = DataFrame(result_in_dict, index=columns) + + return result + + # TODO: Can't use, because mypy doesn't like us setting __name__ # error: "partial[Any]" has no attribute "__name__" # the type is: diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 8afb3ee96ba94..ac7667afbea5f 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -122,10 +122,7 @@ roperator, ) from pandas.core.accessor import CachedAccessor -from pandas.core.apply import ( - reconstruct_func, - relabel_result, -) +from pandas.core.apply import reconstruct_and_relabel_result from pandas.core.array_algos.take import take_2d_multi from pandas.core.arraylike import OpsMixin from pandas.core.arrays import ( @@ -9579,23 +9576,9 @@ def aggregate(self, func=None, axis: Axis = 0, *args, **kwargs): axis = self._get_axis_number(axis) - relabeling, func, columns, order = reconstruct_func(func, **kwargs) - op = frame_apply(self, func=func, axis=axis, args=args, kwargs=kwargs) result = op.agg() - - if relabeling: - # This is to keep the order to columns occurrence unchanged, and also - # keep the order of new columns occurrence unchanged - - # For the return values of reconstruct_func, if relabeling is - # False, columns and order will be None. - assert columns is not None - assert order is not None - - result_in_dict = relabel_result(result, func, columns, order) - result = DataFrame(result_in_dict, index=columns) - + result = reconstruct_and_relabel_result(result, func, **kwargs) return result agg = aggregate diff --git a/pandas/tests/apply/test_frame_apply.py b/pandas/tests/apply/test_frame_apply.py index 80292ac6641ac..fc8b57d26a5be 100644 --- a/pandas/tests/apply/test_frame_apply.py +++ b/pandas/tests/apply/test_frame_apply.py @@ -37,6 +37,13 @@ def test_apply(float_frame): assert result.index is float_frame.index +@pytest.mark.parametrize("axis", [0, 1]) +def test_apply_args(float_frame, axis): + result = float_frame.apply(lambda x, y: x + y, axis, args=(1,)) + expected = float_frame + 1 + tm.assert_frame_equal(result, expected) + + def test_apply_categorical_func(): # GH 9573 df = DataFrame({"c0": ["A", "A", "B", "B"], "c1": ["C", "C", "D", "D"]})