From d63df1028ca6e91853a2848b0f844f12a5153c1c Mon Sep 17 00:00:00 2001 From: Natalia Mokeeva Date: Thu, 28 Mar 2024 00:53:02 +0100 Subject: [PATCH 1/3] move raising for interpolate with object dtype from NDFrame to Block --- pandas/core/generic.py | 5 ----- pandas/core/internals/blocks.py | 5 +++-- pandas/tests/copy_view/test_interp_fillna.py | 2 +- pandas/tests/frame/methods/test_interpolate.py | 8 ++++---- pandas/tests/series/methods/test_interpolate.py | 8 +++----- 5 files changed, 11 insertions(+), 17 deletions(-) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index a7545fb8d98de..393611abda551 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -7788,11 +7788,6 @@ def interpolate( raise ValueError("'method' should be a string, not None.") obj, should_transpose = (self.T, True) if axis == 1 else (self, False) - # GH#53631 - if np.any(obj.dtypes == object): - raise TypeError( - f"{type(self).__name__} cannot interpolate with object dtype." - ) if isinstance(obj.index, MultiIndex) and method != "linear": raise ValueError( diff --git a/pandas/core/internals/blocks.py b/pandas/core/internals/blocks.py index a7cdc7c39754d..d327461f3d6d4 100644 --- a/pandas/core/internals/blocks.py +++ b/pandas/core/internals/blocks.py @@ -1393,12 +1393,13 @@ def interpolate( # If there are no NAs, then interpolate is a no-op return [self.copy(deep=False)] - # TODO(3.0): this case will not be reachable once GH#53638 is enforced if self.dtype == _dtype_obj: # only deal with floats # bc we already checked that can_hold_na, we don't have int dtype here # test_interp_basic checks that we make a copy here - return [self.copy(deep=False)] + raise TypeError( + f"{type(self).__name__} cannot interpolate with object dtype." + ) copy, refs = self._get_refs_and_copy(inplace) diff --git a/pandas/tests/copy_view/test_interp_fillna.py b/pandas/tests/copy_view/test_interp_fillna.py index abd87162ec32e..2d394f6e19eb7 100644 --- a/pandas/tests/copy_view/test_interp_fillna.py +++ b/pandas/tests/copy_view/test_interp_fillna.py @@ -113,7 +113,7 @@ def test_interp_fill_functions_inplace(func, dtype): def test_interpolate_cannot_with_object_dtype(): df = DataFrame({"a": ["a", np.nan, "c"], "b": 1}) - msg = "DataFrame cannot interpolate with object dtype" + msg = "NumpyBlock cannot interpolate with object dtype" with pytest.raises(TypeError, match=msg): df.interpolate() diff --git a/pandas/tests/frame/methods/test_interpolate.py b/pandas/tests/frame/methods/test_interpolate.py index 0a9d059736e6f..462a552243ed4 100644 --- a/pandas/tests/frame/methods/test_interpolate.py +++ b/pandas/tests/frame/methods/test_interpolate.py @@ -76,7 +76,7 @@ def test_interp_basic(self): "D": list("abcd"), } ) - msg = "DataFrame cannot interpolate with object dtype" + msg = ".* cannot interpolate with object dtype" with pytest.raises(TypeError, match=msg): df.interpolate() @@ -102,7 +102,7 @@ def test_interp_basic_with_non_range_index(self, using_infer_string): } ) - msg = "DataFrame cannot interpolate with object dtype" + msg = ".* cannot interpolate with object dtype" if not using_infer_string: with pytest.raises(TypeError, match=msg): df.set_index("C").interpolate() @@ -296,14 +296,14 @@ def test_interp_raise_on_only_mixed(self, axis): "E": [1, 2, 3, 4], } ) - msg = "DataFrame cannot interpolate with object dtype" + msg = ".* cannot interpolate with object dtype" with pytest.raises(TypeError, match=msg): df.astype("object").interpolate(axis=axis) def test_interp_raise_on_all_object_dtype(self): # GH 22985 df = DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}, dtype="object") - msg = "DataFrame cannot interpolate with object dtype" + msg = ".* cannot interpolate with object dtype" with pytest.raises(TypeError, match=msg): df.interpolate() diff --git a/pandas/tests/series/methods/test_interpolate.py b/pandas/tests/series/methods/test_interpolate.py index c5df1fd498938..1008c2c87dc9e 100644 --- a/pandas/tests/series/methods/test_interpolate.py +++ b/pandas/tests/series/methods/test_interpolate.py @@ -790,11 +790,9 @@ def test_interpolate_unsorted_index(self, ascending, expected_values): def test_interpolate_asfreq_raises(self): ser = Series(["a", None, "b"], dtype=object) - msg2 = "Series cannot interpolate with object dtype" - msg = "Invalid fill method" - with pytest.raises(TypeError, match=msg2): - with pytest.raises(ValueError, match=msg): - ser.interpolate(method="asfreq") + msg = "Can not interpolate with method=asfreq" + with pytest.raises(ValueError, match=msg): + ser.interpolate(method="asfreq") def test_interpolate_fill_value(self): # GH#54920 From e3d86c83daddfb61f17adae1640c9c5ebddc6184 Mon Sep 17 00:00:00 2001 From: Natalia Mokeeva Date: Sat, 30 Mar 2024 01:48:57 +0100 Subject: [PATCH 2/3] correct msg in test_interpolate_cannot_with_object_dtype --- pandas/tests/copy_view/test_interp_fillna.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tests/copy_view/test_interp_fillna.py b/pandas/tests/copy_view/test_interp_fillna.py index 2d394f6e19eb7..e1ecb06239a0c 100644 --- a/pandas/tests/copy_view/test_interp_fillna.py +++ b/pandas/tests/copy_view/test_interp_fillna.py @@ -113,7 +113,7 @@ def test_interp_fill_functions_inplace(func, dtype): def test_interpolate_cannot_with_object_dtype(): df = DataFrame({"a": ["a", np.nan, "c"], "b": 1}) - msg = "NumpyBlock cannot interpolate with object dtype" + msg = ".* cannot interpolate with object dtype" with pytest.raises(TypeError, match=msg): df.interpolate() From 7072d0fb0517f8182c17edddb4ec7a4bb6ddc256 Mon Sep 17 00:00:00 2001 From: Natalia Mokeeva Date: Sun, 31 Mar 2024 13:39:29 +0200 Subject: [PATCH 3/3] correct the exception message and the comments --- pandas/core/internals/blocks.py | 9 +++------ pandas/tests/copy_view/test_interp_fillna.py | 2 +- pandas/tests/frame/methods/test_interpolate.py | 8 ++++---- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/pandas/core/internals/blocks.py b/pandas/core/internals/blocks.py index f1087a92bf45b..7be1d5d95ffdf 100644 --- a/pandas/core/internals/blocks.py +++ b/pandas/core/internals/blocks.py @@ -1389,12 +1389,9 @@ def interpolate( return [self.copy(deep=False)] if self.dtype == _dtype_obj: - # only deal with floats - # bc we already checked that can_hold_na, we don't have int dtype here - # test_interp_basic checks that we make a copy here - raise TypeError( - f"{type(self).__name__} cannot interpolate with object dtype." - ) + # GH#53631 + name = {1: "Series", 2: "DataFrame"}[self.ndim] + raise TypeError(f"{name} cannot interpolate with object dtype.") copy, refs = self._get_refs_and_copy(inplace) diff --git a/pandas/tests/copy_view/test_interp_fillna.py b/pandas/tests/copy_view/test_interp_fillna.py index e1ecb06239a0c..abd87162ec32e 100644 --- a/pandas/tests/copy_view/test_interp_fillna.py +++ b/pandas/tests/copy_view/test_interp_fillna.py @@ -113,7 +113,7 @@ def test_interp_fill_functions_inplace(func, dtype): def test_interpolate_cannot_with_object_dtype(): df = DataFrame({"a": ["a", np.nan, "c"], "b": 1}) - msg = ".* cannot interpolate with object dtype" + msg = "DataFrame cannot interpolate with object dtype" with pytest.raises(TypeError, match=msg): df.interpolate() diff --git a/pandas/tests/frame/methods/test_interpolate.py b/pandas/tests/frame/methods/test_interpolate.py index 462a552243ed4..0a9d059736e6f 100644 --- a/pandas/tests/frame/methods/test_interpolate.py +++ b/pandas/tests/frame/methods/test_interpolate.py @@ -76,7 +76,7 @@ def test_interp_basic(self): "D": list("abcd"), } ) - msg = ".* cannot interpolate with object dtype" + msg = "DataFrame cannot interpolate with object dtype" with pytest.raises(TypeError, match=msg): df.interpolate() @@ -102,7 +102,7 @@ def test_interp_basic_with_non_range_index(self, using_infer_string): } ) - msg = ".* cannot interpolate with object dtype" + msg = "DataFrame cannot interpolate with object dtype" if not using_infer_string: with pytest.raises(TypeError, match=msg): df.set_index("C").interpolate() @@ -296,14 +296,14 @@ def test_interp_raise_on_only_mixed(self, axis): "E": [1, 2, 3, 4], } ) - msg = ".* cannot interpolate with object dtype" + msg = "DataFrame cannot interpolate with object dtype" with pytest.raises(TypeError, match=msg): df.astype("object").interpolate(axis=axis) def test_interp_raise_on_all_object_dtype(self): # GH 22985 df = DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}, dtype="object") - msg = ".* cannot interpolate with object dtype" + msg = "DataFrame cannot interpolate with object dtype" with pytest.raises(TypeError, match=msg): df.interpolate()