Skip to content

Commit 279a89e

Browse files
committed
simplify first_compat and last_compat
1 parent be54f6c commit 279a89e

File tree

1 file changed

+35
-19
lines changed

1 file changed

+35
-19
lines changed

pandas/core/groupby/groupby.py

+35-19
Original file line numberDiff line numberDiff line change
@@ -1165,6 +1165,27 @@ def _apply_filter(self, indices, dropna):
11651165
OutputFrameOrSeries = TypeVar("OutputFrameOrSeries", bound=NDFrame)
11661166

11671167

1168+
def get_loc_notna(obj: "Series", *, loc: int):
1169+
"""Find the value in position ``loc`` after filtering ``obj`` for nan values.
1170+
1171+
if ``obj`` is empty or has only nan values, np.nan er returned.
1172+
1173+
Examples
1174+
--------
1175+
>>> ser = pd.Series([np.nan, np.nan, 1, 2, np.nan])
1176+
>>> get_loc_notna(ser, loc=0) # get first non-na
1177+
1.0
1178+
>>> get_loc_notna(ser, loc=-1) # get last non-na
1179+
2.0
1180+
"""
1181+
x = obj.to_numpy()
1182+
x = x[notna(x)]
1183+
1184+
if len(x) == 0:
1185+
return np.nan
1186+
return x[loc]
1187+
1188+
11681189
class GroupBy(_GroupBy[FrameOrSeries]):
11691190
"""
11701191
Class for grouping and aggregating relational data.
@@ -1510,26 +1531,15 @@ def max(self, numeric_only: bool = False, min_count: int = -1):
15101531
numeric_only=numeric_only, min_count=min_count, alias="max", npfunc=np.max
15111532
)
15121533

1513-
@staticmethod
1514-
def _get_loc(x, axis: int = 0, *, loc: int):
1515-
"""Helper function for first/last item that isn't NA.
1516-
"""
1517-
1518-
def get_loc_notna(x, loc: int):
1519-
x = x.to_numpy()
1520-
x = x[notna(x)]
1521-
if len(x) == 0:
1522-
return np.nan
1523-
return x[loc]
1524-
1525-
if isinstance(x, DataFrame):
1526-
return x.apply(get_loc_notna, axis=axis, loc=loc)
1527-
else:
1528-
return get_loc_notna(x, loc=loc)
1529-
15301534
@doc(_groupby_agg_method_template, fname="first", no=False, mc=-1)
15311535
def first(self, numeric_only: bool = False, min_count: int = -1):
1532-
first_compat = partial(self._get_loc, loc=0)
1536+
def first_compat(x, axis: int = 0):
1537+
"""Helper function for first item that isn't NA.
1538+
"""
1539+
if isinstance(x, DataFrame):
1540+
return x.apply(get_loc_notna, axis=axis, loc=0)
1541+
else:
1542+
return get_loc_notna(x, loc=0)
15331543

15341544
return self._agg_general(
15351545
numeric_only=numeric_only,
@@ -1540,7 +1550,13 @@ def first(self, numeric_only: bool = False, min_count: int = -1):
15401550

15411551
@doc(_groupby_agg_method_template, fname="last", no=False, mc=-1)
15421552
def last(self, numeric_only: bool = False, min_count: int = -1):
1543-
last_compat = partial(self._get_loc, loc=-1)
1553+
def last_compat(x, axis: int = 0):
1554+
"""Helper function for last item that isn't NA.
1555+
"""
1556+
if isinstance(x, DataFrame):
1557+
return x.apply(get_loc_notna, axis=axis, loc=-1)
1558+
else:
1559+
return get_loc_notna(x, loc=-1)
15441560

15451561
return self._agg_general(
15461562
numeric_only=numeric_only,

0 commit comments

Comments
 (0)