Skip to content

Commit 221c3aa

Browse files
authored
PERF: avoid copies in frame[col].fillna(val, inplace=True) GH#46149 (#46204)
1 parent 3e718e3 commit 221c3aa

File tree

4 files changed

+23
-1
lines changed

4 files changed

+23
-1
lines changed

doc/source/whatsnew/v1.4.2.rst

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ including other versions of pandas.
1515
Fixed regressions
1616
~~~~~~~~~~~~~~~~~
1717
- Fixed regression in :meth:`DataFrame.drop` and :meth:`Series.drop` when :class:`Index` had extension dtype and duplicates (:issue:`45860`)
18+
- Fixed memory performance regression in :meth:`Series.fillna` when called on a :class:`DataFrame` column with ``inplace=True`` (:issue:`46149`)
1819
-
1920

2021
.. ---------------------------------------------------------------------------

pandas/core/frame.py

+6
Original file line numberDiff line numberDiff line change
@@ -3960,6 +3960,12 @@ def _maybe_cache_changed(self, item, value: Series, inplace: bool) -> None:
39603960
"""
39613961
loc = self._info_axis.get_loc(item)
39623962
arraylike = value._values
3963+
3964+
old = self._ixs(loc, axis=1)
3965+
if old._values is value._values and inplace:
3966+
# GH#46149 avoid making unnecessary copies/block-splitting
3967+
return
3968+
39633969
self._mgr.iset(loc, arraylike, inplace=inplace)
39643970

39653971
# ----------------------------------------------------------------------

pandas/core/generic.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -4368,7 +4368,7 @@ def _update_inplace(self, result, verify_is_copy: bool_t = True) -> None:
43684368
self._reset_cache()
43694369
self._clear_item_cache()
43704370
self._mgr = result._mgr
4371-
self._maybe_update_cacher(verify_is_copy=verify_is_copy)
4371+
self._maybe_update_cacher(verify_is_copy=verify_is_copy, inplace=True)
43724372

43734373
@final
43744374
def add_prefix(self: NDFrameT, prefix: str) -> NDFrameT:

pandas/tests/frame/methods/test_fillna.py

+15
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import numpy as np
22
import pytest
33

4+
import pandas.util._test_decorators as td
5+
46
from pandas import (
57
Categorical,
68
DataFrame,
@@ -17,6 +19,19 @@
1719

1820

1921
class TestFillNA:
22+
@td.skip_array_manager_not_yet_implemented
23+
def test_fillna_on_column_view(self):
24+
# GH#46149 avoid unnecessary copies
25+
arr = np.full((40, 50), np.nan)
26+
df = DataFrame(arr)
27+
28+
df[0].fillna(-1, inplace=True)
29+
assert (arr[:, 0] == -1).all()
30+
31+
# i.e. we didn't create a new 49-column block
32+
assert len(df._mgr.arrays) == 1
33+
assert np.shares_memory(df.values, arr)
34+
2035
def test_fillna_datetime(self, datetime_frame):
2136
tf = datetime_frame
2237
tf.loc[tf.index[:5], "A"] = np.nan

0 commit comments

Comments
 (0)