Skip to content

Commit

Permalink
BUG: DataFrame.interpolate failing to return a copy (pandas-dev#45791)
Browse files Browse the repository at this point in the history
  • Loading branch information
jbrockmendel authored and phofl committed Feb 14, 2022
1 parent de68dad commit ad3e6fc
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 13 deletions.
1 change: 1 addition & 0 deletions doc/source/whatsnew/v1.5.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ Indexing
Missing
^^^^^^^
- Bug in :meth:`Series.fillna` and :meth:`DataFrame.fillna` with ``downcast`` keyword not being respected in some cases where there are no NA values present (:issue:`45423`)
- Bug in :meth:`DataFrame.interpolate` with object-dtype column not returning a copy with ``inplace=False`` (:issue:`45791`)
-

MultiIndex
Expand Down
1 change: 0 additions & 1 deletion pandas/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -6448,7 +6448,6 @@ def fillna(
axis=axis,
limit=limit,
inplace=inplace,
coerce=True,
downcast=downcast,
)
else:
Expand Down
22 changes: 10 additions & 12 deletions pandas/core/internals/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -1024,7 +1024,6 @@ def interpolate(
limit_direction: str = "forward",
limit_area: str | None = None,
fill_value: Any | None = None,
coerce: bool = False,
downcast: str | None = None,
**kwargs,
) -> list[Block]:
Expand All @@ -1035,6 +1034,16 @@ def interpolate(
# If there are no NAs, then interpolate is a no-op
return [self] if inplace else [self.copy()]

try:
m = missing.clean_fill_method(method)
except ValueError:
m = None
if m is None and self.dtype.kind != "f":
# only deal with floats
# bc we already checked that can_hold_na, we dont have int dtype here
# test_interp_basic checks that we make a copy here
return [self] if inplace else [self.copy()]

if self.is_object and self.ndim == 2 and self.shape[0] != 1 and axis == 0:
# split improves performance in ndarray.copy()
return self.split_and_operate(
Expand All @@ -1047,21 +1056,10 @@ def interpolate(
limit_direction,
limit_area,
fill_value,
coerce,
downcast,
**kwargs,
)

try:
m = missing.clean_fill_method(method)
except ValueError:
m = None
if m is None and self.dtype.kind != "f":
# only deal with floats
# bc we already checked that can_hold_na, we dont have int dtype here
# TODO: make a copy if not inplace?
return [self]

data = self.values if inplace else self.values.copy()
data = cast(np.ndarray, data) # bc overridden by ExtensionBlock

Expand Down
32 changes: 32 additions & 0 deletions pandas/tests/frame/methods/test_interpolate.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,38 @@ def test_interp_basic(self):
result = df.interpolate()
tm.assert_frame_equal(result, expected)

# check we didn't operate inplace GH#45791
cvalues = df["C"]._values
dvalues = df["D"].values
assert not np.shares_memory(cvalues, result["C"]._values)
assert not np.shares_memory(dvalues, result["D"]._values)

res = df.interpolate(inplace=True)
assert res is None
tm.assert_frame_equal(df, expected)

# check we DID operate inplace
assert np.shares_memory(df["C"]._values, cvalues)
assert np.shares_memory(df["D"]._values, dvalues)

def test_interp_basic_with_non_range_index(self):
df = DataFrame(
{
"A": [1, 2, np.nan, 4],
"B": [1, 4, 9, np.nan],
"C": [1, 2, 3, 5],
"D": list("abcd"),
}
)
expected = DataFrame(
{
"A": [1.0, 2.0, 3.0, 4.0],
"B": [1.0, 4.0, 9.0, 9.0],
"C": [1, 2, 3, 5],
"D": list("abcd"),
}
)

result = df.set_index("C").interpolate()
expected = df.set_index("C")
expected.loc[3, "A"] = 3
Expand Down

0 comments on commit ad3e6fc

Please sign in to comment.