Skip to content

Commit 36da63f

Browse files
committed
BUG: Series.replace with CoW when made from an Index
1 parent e4a03b6 commit 36da63f

File tree

2 files changed

+23
-8
lines changed

2 files changed

+23
-8
lines changed

pandas/core/internals/blocks.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
final,
1111
)
1212
import warnings
13-
import weakref
1413

1514
import numpy as np
1615

@@ -863,14 +862,22 @@ def replace_list(
863862
)
864863

865864
if i != src_len:
866-
# This is ugly, but we have to get rid of intermediate refs
867-
# that did not go out of scope yet, otherwise we will trigger
868-
# many unnecessary copies
865+
# This is ugly, but we have to get rid of intermediate refs. We
866+
# can simply clear the referenced_blocks if we already copied,
867+
# otherwise we have to remove ourselves
868+
self_blk_ids = {
869+
id(b()): i for i, b in enumerate(self.refs.referenced_blocks)
870+
}
869871
for b in result:
870-
ref = weakref.ref(b)
871-
b.refs.referenced_blocks.pop(
872-
b.refs.referenced_blocks.index(ref)
873-
)
872+
if b.refs is self.refs:
873+
# We are still sharing memory with self
874+
if id(b) in self_blk_ids:
875+
# Remove ourselves from the refs; we are temporary
876+
self.refs.referenced_blocks.pop(self_blk_ids[id(b)])
877+
else:
878+
# We have already copied, so we can clear the refs to avoid
879+
# future copies
880+
b.refs.referenced_blocks.clear()
874881
new_rb.extend(result)
875882
rb = new_rb
876883
return rb

pandas/tests/series/methods/test_replace.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -715,3 +715,11 @@ def test_replace_all_NA(self):
715715
result = df.replace({r"^#": "$"}, regex=True)
716716
expected = pd.Series([pd.NA, pd.NA])
717717
tm.assert_series_equal(result, expected)
718+
719+
720+
def test_replace_from_index():
721+
# https://github.com/pandas-dev/pandas/issues/61622
722+
idx = pd.Index(["a", "b", "c"], dtype="string[pyarrow]")
723+
expected = pd.Series(["d", "b", "c"], dtype="string[pyarrow]")
724+
result = pd.Series(idx).replace({"z": "b", "a": "d"})
725+
tm.assert_series_equal(result, expected)

0 commit comments

Comments
 (0)