diff --git a/pandas/core/arrays/datetimelike.py b/pandas/core/arrays/datetimelike.py index 8c57496e092c4..ea085b3d1f6ab 100644 --- a/pandas/core/arrays/datetimelike.py +++ b/pandas/core/arrays/datetimelike.py @@ -106,6 +106,7 @@ from pandas.core import ( algorithms, + missing, nanops, ) from pandas.core.algorithms import ( @@ -142,6 +143,7 @@ from pandas.tseries import frequencies if TYPE_CHECKING: + from pandas import Index from pandas.core.arrays import ( DatetimeArray, PeriodArray, @@ -2228,6 +2230,46 @@ def copy(self, order: str = "C") -> Self: new_obj._freq = self.freq return new_obj + def interpolate( + self, + *, + method, + axis: int, + index: Index | None, + limit, + limit_direction, + limit_area, + fill_value, + inplace: bool, + **kwargs, + ) -> Self: + """ + See NDFrame.interpolate.__doc__. + """ + # NB: we return type(self) even if inplace=True + if method != "linear": + raise NotImplementedError + + if inplace: + out_data = self._ndarray + else: + out_data = self._ndarray.copy() + + missing.interpolate_array_2d( + out_data, + method=method, + axis=axis, + index=index, + limit=limit, + limit_direction=limit_direction, + limit_area=limit_area, + fill_value=fill_value, + **kwargs, + ) + if inplace: + return self + return type(self)._simple_new(out_data, dtype=self.dtype) + # ------------------------------------------------------------------- # Shared Constructor Helpers diff --git a/pandas/core/arrays/numpy_.py b/pandas/core/arrays/numpy_.py index 702180b5d779a..113f22ad968bc 100644 --- a/pandas/core/arrays/numpy_.py +++ b/pandas/core/arrays/numpy_.py @@ -19,6 +19,7 @@ from pandas.core import ( arraylike, + missing, nanops, ops, ) @@ -33,9 +34,12 @@ Dtype, NpDtype, Scalar, + Self, npt, ) + from pandas import Index + # error: Definition of "_concat_same_type" in base class "NDArrayBacked" is # incompatible with definition in base class "ExtensionArray" @@ -220,6 +224,43 @@ def _values_for_factorize(self) -> tuple[np.ndarray, float | None]: fv = np.nan return self._ndarray, fv + def interpolate( + self, + *, + method, + axis: int, + index: Index | None, + limit, + limit_direction, + limit_area, + fill_value, + inplace: bool, + **kwargs, + ) -> Self: + """ + See NDFrame.interpolate.__doc__. + """ + # NB: we return type(self) even if inplace=True + if inplace: + out_data = self._ndarray + else: + out_data = self._ndarray.copy() + + missing.interpolate_array_2d( + out_data, + method=method, + axis=axis, + index=index, + limit=limit, + limit_direction=limit_direction, + limit_area=limit_area, + fill_value=fill_value, + **kwargs, + ) + if inplace: + return self + return type(self)._simple_new(out_data, dtype=self.dtype) + # ------------------------------------------------------------------------ # Reductions diff --git a/pandas/core/internals/blocks.py b/pandas/core/internals/blocks.py index 7c5d686d96939..696884e344e40 100644 --- a/pandas/core/internals/blocks.py +++ b/pandas/core/internals/blocks.py @@ -1394,18 +1394,16 @@ def interpolate( ) refs = None + arr_inplace = inplace if inplace: if using_cow and self.refs.has_reference(): - data = self.values.copy() + arr_inplace = False else: - data = self.values refs = self.refs - else: - data = self.values.copy() - data = cast(np.ndarray, data) # bc overridden by ExtensionBlock - missing.interpolate_array_2d( - data, + # Dispatch to the PandasArray method. + # We know self.array_values is a PandasArray bc EABlock overrides + new_values = cast(PandasArray, self.array_values).interpolate( method=method, axis=axis, index=index, @@ -1413,8 +1411,10 @@ def interpolate( limit_direction=limit_direction, limit_area=limit_area, fill_value=fill_value, + inplace=arr_inplace, **kwargs, ) + data = new_values._ndarray nb = self.make_block_same_class(data, refs=refs) return nb._maybe_downcast([nb], downcast, using_cow) @@ -2262,18 +2262,22 @@ def interpolate( if method == "linear": # type: ignore[comparison-overlap] # TODO: GH#50950 implement for arbitrary EAs refs = None + arr_inplace = inplace if using_cow: if inplace and not self.refs.has_reference(): - data_out = values._ndarray refs = self.refs else: - data_out = values._ndarray.copy() - else: - data_out = values._ndarray if inplace else values._ndarray.copy() - missing.interpolate_array_2d( - data_out, method=method, limit=limit, index=index, axis=axis + arr_inplace = False + + new_values = self.values.interpolate( + method=method, + index=index, + axis=axis, + inplace=arr_inplace, + limit=limit, + fill_value=fill_value, + **kwargs, ) - new_values = type(values)._simple_new(data_out, dtype=values.dtype) return self.make_block_same_class(new_values, refs=refs) elif values.ndim == 2 and axis == 0: