Skip to content

Commit a5ae33a

Browse files
REGR: setting column with setitem should not modify existing array inplace
1 parent 591da6b commit a5ae33a

File tree

4 files changed

+38
-4
lines changed

4 files changed

+38
-4
lines changed

pandas/core/indexing.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1684,15 +1684,21 @@ def isetter(loc, v):
16841684
com.is_null_slice(idx) or com.is_full_slice(idx, len(self.obj))
16851685
for idx in pi
16861686
):
1687-
ser = v
1687+
if ser._mgr.any_extension_types:
1688+
# avoid `iset` for extension arrays, as this doesn't
1689+
# change the underlying values inplace (GH33457)
1690+
ser._mgr = ser._mgr.setitem(indexer=pi, value=v)
1691+
else:
1692+
ser = v
1693+
self.obj._iset_item(loc, ser)
16881694
else:
16891695
# set the item, possibly having a dtype change
16901696
ser = ser.copy()
16911697
ser._mgr = ser._mgr.setitem(indexer=pi, value=v)
16921698
ser._maybe_update_cacher(clear=True)
16931699

1694-
# reset the sliced object if unique
1695-
self.obj._iset_item(loc, ser)
1700+
# reset the sliced object if unique
1701+
self.obj._iset_item(loc, ser)
16961702

16971703
# we need an iterable, with a ndim of at least 1
16981704
# eg. don't pass through np.array(0)

pandas/core/internals/blocks.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1589,7 +1589,7 @@ def should_store(self, value: ArrayLike) -> bool:
15891589

15901590
def set(self, locs, values):
15911591
assert locs.tolist() == [0]
1592-
self.values[:] = values
1592+
self.values = values
15931593

15941594
def putmask(
15951595
self, mask, new, inplace: bool = False, axis: int = 0, transpose: bool = False,

pandas/tests/indexing/test_iloc.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,15 @@ def test_iloc_setitem_categorical_updates_inplace(self):
705705
expected = pd.Categorical(["C", "B", "A"])
706706
tm.assert_categorical_equal(cat, expected)
707707

708+
# __setitem__ under the other hand does not work in-place
709+
cat = pd.Categorical(["A", "B", "C"])
710+
df = pd.DataFrame({1: cat, 2: [1, 2, 3]})
711+
712+
df["cat"] = cat[::-1]
713+
714+
expected = pd.Categorical(["A", "B", "C"])
715+
tm.assert_categorical_equal(cat, expected)
716+
708717
def test_iloc_with_boolean_operation(self):
709718
# GH 20627
710719
result = DataFrame([[0, 1], [2, 3], [4, 5], [6, np.nan]])

pandas/tests/indexing/test_indexing.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,3 +1100,22 @@ def test_long_text_missing_labels_inside_loc_error_message_limited():
11001100
error_message_regex = "long_missing_label_text_0.*\\\\n.*long_missing_label_text_1"
11011101
with pytest.raises(KeyError, match=error_message_regex):
11021102
s.loc[["a", "c"] + missing_labels]
1103+
1104+
1105+
def test_setitem_EA_column_update():
1106+
# https://github.com/pandas-dev/pandas/issues/33457
1107+
1108+
df = pd.DataFrame(
1109+
{
1110+
"int": [1, 2, 3],
1111+
"int2": [3, 4, 5],
1112+
"float": [0.1, 0.2, 0.3],
1113+
"EA": pd.array([1, 2, None], dtype="Int64"),
1114+
}
1115+
)
1116+
original_arr = df.EA.array
1117+
1118+
# overwrite column with new array
1119+
df["EA"] = pd.array([1, 2, 3], dtype="Int64")
1120+
assert original_arr is not df.EA.array
1121+
tm.assert_extension_array_equal(original_arr, pd.array([1, 2, None], dtype="Int64"))

0 commit comments

Comments
 (0)