Skip to content

Commit bc8bdae

Browse files
meeseeksmachinejorisvandenbossche
authored andcommitted
Backport PR #27855: BUG: add back check for MultiIndex case and take_split_path (#27887)
1 parent 4659bbd commit bc8bdae

File tree

3 files changed

+35
-1
lines changed

3 files changed

+35
-1
lines changed

doc/source/whatsnew/v0.25.1.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ Indexing
8484

8585
- Bug in partial-string indexing returning a NumPy array rather than a ``Series`` when indexing with a scalar like ``.loc['2015']`` (:issue:`27516`)
8686
- Break reference cycle involving :class:`Index` to allow garbage collection of :class:`Index` objects without running the GC. (:issue:`27585`)
87-
-
87+
- Fix regression in assigning values to a single column of a DataFrame with a ``MultiIndex`` columns (:issue:`27841`).
8888
-
8989

9090
Missing

pandas/core/indexing.py

+11
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,17 @@ def _setitem_with_indexer(self, indexer, value):
326326
val = list(value.values()) if isinstance(value, dict) else value
327327
take_split_path = not blk._can_hold_element(val)
328328

329+
# if we have any multi-indexes that have non-trivial slices
330+
# (not null slices) then we must take the split path, xref
331+
# GH 10360, GH 27841
332+
if isinstance(indexer, tuple) and len(indexer) == len(self.obj.axes):
333+
for i, ax in zip(indexer, self.obj.axes):
334+
if isinstance(ax, MultiIndex) and not (
335+
is_integer(i) or com.is_null_slice(i)
336+
):
337+
take_split_path = True
338+
break
339+
329340
if isinstance(indexer, tuple):
330341
nindexer = []
331342
for i, idx in enumerate(indexer):

pandas/tests/indexing/multiindex/test_loc.py

+23
Original file line numberDiff line numberDiff line change
@@ -390,3 +390,26 @@ def test_loc_getitem_lowerdim_corner(multiindex_dataframe_random_data):
390390
expected = 0
391391
result = df.sort_index().loc[("bar", "three"), "B"]
392392
assert result == expected
393+
394+
395+
def test_loc_setitem_single_column_slice():
396+
# case from https://github.com/pandas-dev/pandas/issues/27841
397+
df = DataFrame(
398+
"string",
399+
index=list("abcd"),
400+
columns=MultiIndex.from_product([["Main"], ("another", "one")]),
401+
)
402+
df["labels"] = "a"
403+
df.loc[:, "labels"] = df.index
404+
tm.assert_numpy_array_equal(np.asarray(df["labels"]), np.asarray(df.index))
405+
406+
# test with non-object block
407+
df = DataFrame(
408+
np.nan,
409+
index=range(4),
410+
columns=MultiIndex.from_tuples([("A", "1"), ("A", "2"), ("B", "1")]),
411+
)
412+
expected = df.copy()
413+
df.loc[:, "B"] = np.arange(4)
414+
expected.iloc[:, 2] = np.arange(4)
415+
tm.assert_frame_equal(df, expected)

0 commit comments

Comments
 (0)