Skip to content

Commit b118e5b

Browse files
authored
TYP: first_valid_index & last_valid_index (#40535)
1 parent e56403f commit b118e5b

File tree

2 files changed

+25
-12
lines changed

2 files changed

+25
-12
lines changed

pandas/core/generic.py

+7-7
Original file line numberDiff line numberDiff line change
@@ -11138,7 +11138,7 @@ def __ixor__(self, other):
1113811138
# Misc methods
1113911139

1114011140
@final
11141-
def _find_valid_index(self, how: str):
11141+
def _find_valid_index(self, *, how: str) -> Optional[Hashable]:
1114211142
"""
1114311143
Retrieves the index of the first valid value.
1114411144
@@ -11151,16 +11151,16 @@ def _find_valid_index(self, how: str):
1115111151
-------
1115211152
idx_first_valid : type of index
1115311153
"""
11154-
idxpos = find_valid_index(self._values, how)
11154+
idxpos = find_valid_index(self._values, how=how)
1115511155
if idxpos is None:
1115611156
return None
1115711157
return self.index[idxpos]
1115811158

1115911159
@final
1116011160
@doc(position="first", klass=_shared_doc_kwargs["klass"])
11161-
def first_valid_index(self):
11161+
def first_valid_index(self) -> Optional[Hashable]:
1116211162
"""
11163-
Return index for {position} non-NA/null value.
11163+
Return index for {position} non-NA value or None, if no NA value is found.
1116411164
1116511165
Returns
1116611166
-------
@@ -11171,12 +11171,12 @@ def first_valid_index(self):
1117111171
If all elements are non-NA/null, returns None.
1117211172
Also returns None for empty {klass}.
1117311173
"""
11174-
return self._find_valid_index("first")
11174+
return self._find_valid_index(how="first")
1117511175

1117611176
@final
1117711177
@doc(first_valid_index, position="last", klass=_shared_doc_kwargs["klass"])
11178-
def last_valid_index(self):
11179-
return self._find_valid_index("last")
11178+
def last_valid_index(self) -> Optional[Hashable]:
11179+
return self._find_valid_index(how="last")
1118011180

1118111181

1118211182
def _doc_params(cls):

pandas/core/missing.py

+18-5
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ def clean_interp_method(method: str, **kwargs) -> str:
158158
return method
159159

160160

161-
def find_valid_index(values, how: str):
161+
def find_valid_index(values, *, how: str) -> Optional[int]:
162162
"""
163163
Retrieves the index of the first valid value.
164164
@@ -256,8 +256,17 @@ def interpolate_1d(
256256

257257
# These are sets of index pointers to invalid values... i.e. {0, 1, etc...
258258
all_nans = set(np.flatnonzero(invalid))
259-
start_nans = set(range(find_valid_index(yvalues, "first")))
260-
end_nans = set(range(1 + find_valid_index(yvalues, "last"), len(valid)))
259+
260+
first_valid_index = find_valid_index(yvalues, how="first")
261+
if first_valid_index is None: # no nan found in start
262+
first_valid_index = 0
263+
start_nans = set(range(first_valid_index))
264+
265+
last_valid_index = find_valid_index(yvalues, how="last")
266+
if last_valid_index is None: # no nan found in end
267+
last_valid_index = len(yvalues)
268+
end_nans = set(range(1 + last_valid_index, len(valid)))
269+
261270
mid_nans = all_nans - start_nans - end_nans
262271

263272
# Like the sets above, preserve_nans contains indices of invalid values,
@@ -595,8 +604,12 @@ def _interpolate_with_limit_area(
595604
invalid = isna(values)
596605

597606
if not invalid.all():
598-
first = find_valid_index(values, "first")
599-
last = find_valid_index(values, "last")
607+
first = find_valid_index(values, how="first")
608+
if first is None:
609+
first = 0
610+
last = find_valid_index(values, how="last")
611+
if last is None:
612+
last = len(values)
600613

601614
values = interpolate_2d(
602615
values,

0 commit comments

Comments
 (0)