Skip to content

Commit 12aca3c

Browse files
authored
BUG: loc raising error for MultiIndex with bool indexer (#49766)
1 parent a45dcfd commit 12aca3c

File tree

3 files changed

+24
-2
lines changed

3 files changed

+24
-2
lines changed

doc/source/whatsnew/v2.0.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,7 @@ Indexing
663663
^^^^^^^^
664664
- Bug in :meth:`DataFrame.reindex` filling with wrong values when indexing columns and index for ``uint`` dtypes (:issue:`48184`)
665665
- Bug in :meth:`DataFrame.loc` coercing dtypes when setting values with a list indexer (:issue:`49159`)
666+
- Bug in :meth:`DataFrame.loc` raising ``ValueError`` with ``bool`` indexer and :class:`MultiIndex` (:issue:`47687`)
666667
- Bug in :meth:`DataFrame.__setitem__` raising ``ValueError`` when right hand side is :class:`DataFrame` with :class:`MultiIndex` columns (:issue:`49121`)
667668
- Bug in :meth:`DataFrame.reindex` casting dtype to ``object`` when :class:`DataFrame` has single extension array column when re-indexing ``columns`` and ``index`` (:issue:`48190`)
668669
- Bug in :func:`~DataFrame.describe` when formatting percentiles in the resulting index showed more decimals than needed (:issue:`46362`)

pandas/core/indexing.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -1115,9 +1115,12 @@ def _validate_key(self, key, axis: Axis):
11151115
# slice of labels (where start-end in labels)
11161116
# slice of integers (only if in the labels)
11171117
# boolean not in slice and with boolean index
1118+
ax = self.obj._get_axis(axis)
11181119
if isinstance(key, bool) and not (
1119-
is_bool_dtype(self.obj._get_axis(axis))
1120-
or self.obj._get_axis(axis).dtype.name == "boolean"
1120+
is_bool_dtype(ax)
1121+
or ax.dtype.name == "boolean"
1122+
or isinstance(ax, MultiIndex)
1123+
and is_bool_dtype(ax.get_level_values(0))
11211124
):
11221125
raise KeyError(
11231126
f"{key}: boolean label can not be used without a boolean index"

pandas/tests/frame/indexing/test_indexing.py

+18
Original file line numberDiff line numberDiff line change
@@ -1436,6 +1436,24 @@ def test_loc_rhs_empty_warning(self):
14361436
df.loc[:, "a"] = rhs
14371437
tm.assert_frame_equal(df, expected)
14381438

1439+
@pytest.mark.parametrize("indexer", [True, (True,)])
1440+
@pytest.mark.parametrize("dtype", [bool, "boolean"])
1441+
def test_loc_bool_multiindex(self, dtype, indexer):
1442+
# GH#47687
1443+
midx = MultiIndex.from_arrays(
1444+
[
1445+
Series([True, True, False, False], dtype=dtype),
1446+
Series([True, False, True, False], dtype=dtype),
1447+
],
1448+
names=["a", "b"],
1449+
)
1450+
df = DataFrame({"c": [1, 2, 3, 4]}, index=midx)
1451+
result = df.loc[indexer]
1452+
expected = DataFrame(
1453+
{"c": [1, 2]}, index=Index([True, False], name="b", dtype=dtype)
1454+
)
1455+
tm.assert_frame_equal(result, expected)
1456+
14391457

14401458
class TestDataFrameIndexingUInt64:
14411459
def test_setitem(self, uint64_frame):

0 commit comments

Comments
 (0)