Skip to content

Commit 569babb

Browse files
jbrockmendelKevin D Smith
authored and
Kevin D Smith
committed
BUG: iloc.__setitem__ with DataFrame value, multiple blocks, non-unique columns (pandas-dev#36337)
1 parent 1e62b4c commit 569babb

File tree

2 files changed

+48
-10
lines changed

2 files changed

+48
-10
lines changed

pandas/core/indexing.py

+34-10
Original file line numberDiff line numberDiff line change
@@ -1690,18 +1690,42 @@ def _setitem_with_indexer(self, indexer, value):
16901690
sub_indexer = list(indexer)
16911691
multiindex_indexer = isinstance(labels, ABCMultiIndex)
16921692
# TODO: we are implicitly assuming value.columns is unique
1693+
unique_cols = value.columns.is_unique
1694+
1695+
if not unique_cols and value.columns.equals(self.obj.columns):
1696+
# We assume we are already aligned, see
1697+
# test_iloc_setitem_frame_duplicate_columns_multiple_blocks
1698+
for loc in ilocs:
1699+
item = item_labels[loc]
1700+
if item in value:
1701+
sub_indexer[info_axis] = item
1702+
v = self._align_series(
1703+
tuple(sub_indexer),
1704+
value.iloc[:, loc],
1705+
multiindex_indexer,
1706+
)
1707+
else:
1708+
v = np.nan
16931709

1694-
for loc in ilocs:
1695-
item = item_labels[loc]
1696-
if item in value:
1697-
sub_indexer[info_axis] = item
1698-
v = self._align_series(
1699-
tuple(sub_indexer), value[item], multiindex_indexer
1700-
)
1701-
else:
1702-
v = np.nan
1710+
self._setitem_single_column(loc, v, pi)
17031711

1704-
self._setitem_single_column(loc, v, pi)
1712+
elif not unique_cols:
1713+
raise ValueError(
1714+
"Setting with non-unique columns is not allowed."
1715+
)
1716+
1717+
else:
1718+
for loc in ilocs:
1719+
item = item_labels[loc]
1720+
if item in value:
1721+
sub_indexer[info_axis] = item
1722+
v = self._align_series(
1723+
tuple(sub_indexer), value[item], multiindex_indexer
1724+
)
1725+
else:
1726+
v = np.nan
1727+
1728+
self._setitem_single_column(loc, v, pi)
17051729

17061730
# we have an equal len ndarray/convertible to our labels
17071731
# hasattr first, to avoid coercing to ndarray without reason.

pandas/tests/indexing/test_iloc.py

+14
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,20 @@ def test_iloc_setitem_dups(self):
369369
df.iloc[[1, 0], [0, 1]] = df.iloc[[1, 0], [0, 1]].reset_index(drop=True)
370370
tm.assert_frame_equal(df, expected)
371371

372+
def test_iloc_setitem_frame_duplicate_columns_multiple_blocks(self):
373+
# Same as the "assign back to self" check in test_iloc_setitem_dups
374+
# but on a DataFrame with multiple blocks
375+
df = pd.DataFrame([[0, 1], [2, 3]], columns=["B", "B"])
376+
377+
df.iloc[:, 0] = df.iloc[:, 0].astype("f8")
378+
assert len(df._mgr.blocks) == 2
379+
expected = df.copy()
380+
381+
# assign back to self
382+
df.iloc[[0, 1], [0, 1]] = df.iloc[[0, 1], [0, 1]]
383+
384+
tm.assert_frame_equal(df, expected)
385+
372386
# TODO: GH#27620 this test used to compare iloc against ix; check if this
373387
# is redundant with another test comparing iloc against loc
374388
def test_iloc_getitem_frame(self):

0 commit comments

Comments
 (0)