Skip to content

Commit d64d928

Browse files
jbrockmendelJulianWgs
authored andcommitted
REF/TYP: implement NDFrameApply (pandas-dev#41067)
1 parent 00237eb commit d64d928

File tree

1 file changed

+38
-31
lines changed

1 file changed

+38
-31
lines changed

pandas/core/apply.py

+38-31
Original file line numberDiff line numberDiff line change
@@ -137,14 +137,6 @@ def f(x):
137137
self.orig_f: AggFuncType = func
138138
self.f: AggFuncType = f
139139

140-
@property
141-
def index(self) -> Index:
142-
return self.obj.index
143-
144-
@property
145-
def agg_axis(self) -> Index:
146-
return self.obj._get_agg_axis(self.axis)
147-
148140
@abc.abstractmethod
149141
def apply(self) -> FrameOrSeriesUnion:
150142
pass
@@ -163,9 +155,8 @@ def agg(self) -> FrameOrSeriesUnion | None:
163155
args = self.args
164156
kwargs = self.kwargs
165157

166-
result = self.maybe_apply_str()
167-
if result is not None:
168-
return result
158+
if isinstance(arg, str):
159+
return self.maybe_apply_str()
169160

170161
if is_dict_like(arg):
171162
return self.agg_dict_like()
@@ -465,27 +456,20 @@ def agg_dict_like(self) -> FrameOrSeriesUnion:
465456

466457
return result
467458

468-
def maybe_apply_str(self) -> FrameOrSeriesUnion | None:
459+
def maybe_apply_str(self) -> FrameOrSeriesUnion:
469460
"""
470461
Compute apply in case of a string.
471462
472463
Returns
473464
-------
474-
result: Series, DataFrame, or None
475-
Result when self.f is a string, None otherwise.
465+
result: Series or DataFrame
476466
"""
467+
# Caller is responsible for checking isinstance(self.f, str)
477468
f = self.f
478-
if not isinstance(f, str):
479-
return None
469+
f = cast(str, f)
480470

481471
obj = self.obj
482472

483-
# TODO: GH 39993 - Avoid special-casing by replacing with lambda
484-
if f == "size" and isinstance(obj, ABCDataFrame):
485-
# Special-cased because DataFrame.size returns a single scalar
486-
value = obj.shape[self.axis]
487-
return obj._constructor_sliced(value, index=self.agg_axis, name="size")
488-
489473
# Support for `frame.transform('method')`
490474
# Some methods (shift, etc.) require the axis argument, others
491475
# don't, so inspect and insert if necessary.
@@ -587,7 +571,22 @@ def _try_aggregate_string_function(self, obj, arg: str, *args, **kwargs):
587571
)
588572

589573

590-
class FrameApply(Apply):
574+
class NDFrameApply(Apply):
575+
"""
576+
Methods shared by FrameApply and SeriesApply but
577+
not GroupByApply or ResamplerWindowApply
578+
"""
579+
580+
@property
581+
def index(self) -> Index:
582+
return self.obj.index
583+
584+
@property
585+
def agg_axis(self) -> Index:
586+
return self.obj._get_agg_axis(self.axis)
587+
588+
589+
class FrameApply(NDFrameApply):
591590
obj: DataFrame
592591

593592
# ---------------------------------------------------------------
@@ -644,9 +643,8 @@ def apply(self) -> FrameOrSeriesUnion:
644643
return self.apply_empty_result()
645644

646645
# string dispatch
647-
result = self.maybe_apply_str()
648-
if result is not None:
649-
return result
646+
if isinstance(self.f, str):
647+
return self.maybe_apply_str()
650648

651649
# ufunc
652650
elif isinstance(self.f, np.ufunc):
@@ -831,6 +829,16 @@ def wrap_results(self, results: ResType, res_index: Index) -> FrameOrSeriesUnion
831829

832830
return result
833831

832+
def maybe_apply_str(self) -> FrameOrSeriesUnion:
833+
# Caller is responsible for checking isinstance(self.f, str)
834+
# TODO: GH#39993 - Avoid special-casing by replacing with lambda
835+
if self.f == "size":
836+
# Special-cased because DataFrame.size returns a single scalar
837+
obj = self.obj
838+
value = obj.shape[self.axis]
839+
return obj._constructor_sliced(value, index=self.agg_axis, name="size")
840+
return super().maybe_apply_str()
841+
834842

835843
class FrameRowApply(FrameApply):
836844
axis = 0
@@ -967,7 +975,7 @@ def infer_to_same_shape(self, results: ResType, res_index: Index) -> DataFrame:
967975
return result
968976

969977

970-
class SeriesApply(Apply):
978+
class SeriesApply(NDFrameApply):
971979
obj: Series
972980
axis = 0
973981

@@ -1001,10 +1009,9 @@ def apply(self) -> FrameOrSeriesUnion:
10011009
if result is not None:
10021010
return result
10031011

1004-
# if we are a string, try to dispatch
1005-
result = self.maybe_apply_str()
1006-
if result is not None:
1007-
return result
1012+
if isinstance(self.f, str):
1013+
# if we are a string, try to dispatch
1014+
return self.maybe_apply_str()
10081015

10091016
return self.apply_standard()
10101017

0 commit comments

Comments
 (0)