Skip to content

Commit e4e60e4

Browse files
authored
REF: clarify missing.interpolate_2d is inplace (#44210)
1 parent e8faf63 commit e4e60e4

File tree

2 files changed

+41
-39
lines changed

2 files changed

+41
-39
lines changed

pandas/core/arrays/sparse/array.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -743,8 +743,10 @@ def fillna(
743743
elif method is not None:
744744
msg = "fillna with 'method' requires high memory usage."
745745
warnings.warn(msg, PerformanceWarning)
746-
filled = interpolate_2d(np.asarray(self), method=method, limit=limit)
747-
return type(self)(filled, fill_value=self.fill_value)
746+
new_values = np.asarray(self)
747+
# interpolate_2d modifies new_values inplace
748+
interpolate_2d(new_values, method=method, limit=limit)
749+
return type(self)(new_values, fill_value=self.fill_value)
748750

749751
else:
750752
new_values = np.where(isna(self.sp_values), value, self.sp_values)

pandas/core/missing.py

+37-37
Original file line numberDiff line numberDiff line change
@@ -214,9 +214,11 @@ def interpolate_array_2d(
214214
coerce: bool = False,
215215
downcast: str | None = None,
216216
**kwargs,
217-
):
217+
) -> np.ndarray:
218218
"""
219219
Wrapper to dispatch to either interpolate_2d or _interpolate_2d_with_fill.
220+
221+
Returned ndarray has same dtype as 'data'.
220222
"""
221223
try:
222224
m = clean_fill_method(method)
@@ -228,13 +230,14 @@ def interpolate_array_2d(
228230
# similar to validate_fillna_kwargs
229231
raise ValueError("Cannot pass both fill_value and method")
230232

231-
interp_values = interpolate_2d(
233+
interpolate_2d(
232234
data,
233235
method=m,
234236
axis=axis,
235237
limit=limit,
236238
limit_area=limit_area,
237239
)
240+
interp_values = data
238241
else:
239242
assert index is not None # for mypy
240243

@@ -687,14 +690,14 @@ def _cubicspline_interpolate(xi, yi, x, axis=0, bc_type="not-a-knot", extrapolat
687690

688691

689692
def _interpolate_with_limit_area(
690-
values: ArrayLike, method: str, limit: int | None, limit_area: str | None
691-
) -> ArrayLike:
693+
values: np.ndarray, method: str, limit: int | None, limit_area: str | None
694+
) -> None:
692695
"""
693696
Apply interpolation and limit_area logic to values along a to-be-specified axis.
694697
695698
Parameters
696699
----------
697-
values: array-like
700+
values: np.ndarray
698701
Input array.
699702
method: str
700703
Interpolation method. Could be "bfill" or "pad"
@@ -703,10 +706,9 @@ def _interpolate_with_limit_area(
703706
limit_area: str
704707
Limit area for interpolation. Can be "inside" or "outside"
705708
706-
Returns
707-
-------
708-
values: array-like
709-
Interpolated array.
709+
Notes
710+
-----
711+
Modifies values in-place.
710712
"""
711713

712714
invalid = isna(values)
@@ -719,7 +721,7 @@ def _interpolate_with_limit_area(
719721
if last is None:
720722
last = len(values)
721723

722-
values = interpolate_2d(
724+
interpolate_2d(
723725
values,
724726
method=method,
725727
limit=limit,
@@ -732,23 +734,23 @@ def _interpolate_with_limit_area(
732734

733735
values[invalid] = np.nan
734736

735-
return values
737+
return
736738

737739

738740
def interpolate_2d(
739-
values,
741+
values: np.ndarray,
740742
method: str = "pad",
741743
axis: Axis = 0,
742744
limit: int | None = None,
743745
limit_area: str | None = None,
744-
):
746+
) -> None:
745747
"""
746748
Perform an actual interpolation of values, values will be make 2-d if
747749
needed fills inplace, returns the result.
748750
749751
Parameters
750752
----------
751-
values: array-like
753+
values: np.ndarray
752754
Input array.
753755
method: str, default "pad"
754756
Interpolation method. Could be "bfill" or "pad"
@@ -759,13 +761,12 @@ def interpolate_2d(
759761
limit_area: str, optional
760762
Limit area for interpolation. Can be "inside" or "outside"
761763
762-
Returns
763-
-------
764-
values: array-like
765-
Interpolated array.
764+
Notes
765+
-----
766+
Modifies values in-place.
766767
"""
767768
if limit_area is not None:
768-
return np.apply_along_axis(
769+
np.apply_along_axis(
769770
partial(
770771
_interpolate_with_limit_area,
771772
method=method,
@@ -775,32 +776,31 @@ def interpolate_2d(
775776
axis,
776777
values,
777778
)
779+
return
778780

779781
transf = (lambda x: x) if axis == 0 else (lambda x: x.T)
780782

781783
# reshape a 1 dim if needed
782-
ndim = values.ndim
783784
if values.ndim == 1:
784785
if axis != 0: # pragma: no cover
785786
raise AssertionError("cannot interpolate on a ndim == 1 with axis != 0")
786787
values = values.reshape(tuple((1,) + values.shape))
787788

788789
method = clean_fill_method(method)
789790
tvalues = transf(values)
791+
792+
# _pad_2d and _backfill_2d both modify tvalues inplace
790793
if method == "pad":
791-
result, _ = _pad_2d(tvalues, limit=limit)
794+
_pad_2d(tvalues, limit=limit)
792795
else:
793-
result, _ = _backfill_2d(tvalues, limit=limit)
794-
795-
result = transf(result)
796-
# reshape back
797-
if ndim == 1:
798-
result = result[0]
796+
_backfill_2d(tvalues, limit=limit)
799797

800-
return result
798+
return
801799

802800

803-
def _fillna_prep(values, mask: np.ndarray | None = None) -> np.ndarray:
801+
def _fillna_prep(
802+
values, mask: npt.NDArray[np.bool_] | None = None
803+
) -> npt.NDArray[np.bool_]:
804804
# boilerplate for _pad_1d, _backfill_1d, _pad_2d, _backfill_2d
805805

806806
if mask is None:
@@ -834,8 +834,8 @@ def new_func(values, limit=None, mask=None):
834834
def _pad_1d(
835835
values: np.ndarray,
836836
limit: int | None = None,
837-
mask: np.ndarray | None = None,
838-
) -> tuple[np.ndarray, np.ndarray]:
837+
mask: npt.NDArray[np.bool_] | None = None,
838+
) -> tuple[np.ndarray, npt.NDArray[np.bool_]]:
839839
mask = _fillna_prep(values, mask)
840840
algos.pad_inplace(values, mask, limit=limit)
841841
return values, mask
@@ -845,15 +845,15 @@ def _pad_1d(
845845
def _backfill_1d(
846846
values: np.ndarray,
847847
limit: int | None = None,
848-
mask: np.ndarray | None = None,
849-
) -> tuple[np.ndarray, np.ndarray]:
848+
mask: npt.NDArray[np.bool_] | None = None,
849+
) -> tuple[np.ndarray, npt.NDArray[np.bool_]]:
850850
mask = _fillna_prep(values, mask)
851851
algos.backfill_inplace(values, mask, limit=limit)
852852
return values, mask
853853

854854

855855
@_datetimelike_compat
856-
def _pad_2d(values, limit=None, mask=None):
856+
def _pad_2d(values: np.ndarray, limit=None, mask: npt.NDArray[np.bool_] | None = None):
857857
mask = _fillna_prep(values, mask)
858858

859859
if np.all(values.shape):
@@ -865,7 +865,7 @@ def _pad_2d(values, limit=None, mask=None):
865865

866866

867867
@_datetimelike_compat
868-
def _backfill_2d(values, limit=None, mask=None):
868+
def _backfill_2d(values, limit=None, mask: npt.NDArray[np.bool_] | None = None):
869869
mask = _fillna_prep(values, mask)
870870

871871
if np.all(values.shape):
@@ -890,7 +890,7 @@ def clean_reindex_fill_method(method):
890890
return clean_fill_method(method, allow_nearest=True)
891891

892892

893-
def _interp_limit(invalid: np.ndarray, fw_limit, bw_limit):
893+
def _interp_limit(invalid: npt.NDArray[np.bool_], fw_limit, bw_limit):
894894
"""
895895
Get indexers of values that won't be filled
896896
because they exceed the limits.
@@ -955,7 +955,7 @@ def inner(invalid, limit):
955955
return f_idx & b_idx
956956

957957

958-
def _rolling_window(a: np.ndarray, window: int):
958+
def _rolling_window(a: npt.NDArray[np.bool_], window: int) -> npt.NDArray[np.bool_]:
959959
"""
960960
[True, True, False, True, False], 2 ->
961961

0 commit comments

Comments
 (0)