Skip to content

Commit

Permalink
Backport PR pandas-dev#56635: CoW: Boolean indexer in MultiIndex rais…
Browse files Browse the repository at this point in the history
…ing read-only error
  • Loading branch information
phofl authored and meeseeksmachine committed Dec 28, 2023
1 parent f99f4d6 commit a78f3db
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 0 deletions.
1 change: 1 addition & 0 deletions doc/source/whatsnew/v2.2.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,7 @@ Interval

Indexing
^^^^^^^^
- Bug in :meth:`DataFrame.loc` mutating a boolean indexer when :class:`DataFrame` has a :class:`MultiIndex` (:issue:`56635`)
- Bug in :meth:`DataFrame.loc` when setting :class:`Series` with extension dtype into NumPy dtype (:issue:`55604`)
- Bug in :meth:`Index.difference` not returning a unique set of values when ``other`` is empty or ``other`` is considered non-comparable (:issue:`55113`)
- Bug in setting :class:`Categorical` values into a :class:`DataFrame` with numpy dtypes raising ``RecursionError`` (:issue:`52927`)
Expand Down
2 changes: 2 additions & 0 deletions pandas/core/indexes/multi.py
Original file line number Diff line number Diff line change
Expand Up @@ -3488,6 +3488,8 @@ def _to_bool_indexer(indexer) -> npt.NDArray[np.bool_]:
"is not the same length as the index"
)
lvl_indexer = np.asarray(k)
if indexer is None:
lvl_indexer = lvl_indexer.copy()

elif is_list_like(k):
# a collection of labels to include from this level (these are or'd)
Expand Down
21 changes: 21 additions & 0 deletions pandas/tests/copy_view/test_indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -1224,6 +1224,27 @@ def test_series_midx_tuples_slice(using_copy_on_write, warn_copy_on_write):
tm.assert_series_equal(ser, expected)


def test_midx_read_only_bool_indexer():
# GH#56635
def mklbl(prefix, n):
return [f"{prefix}{i}" for i in range(n)]

idx = pd.MultiIndex.from_product(
[mklbl("A", 4), mklbl("B", 2), mklbl("C", 4), mklbl("D", 2)]
)
cols = pd.MultiIndex.from_tuples(
[("a", "foo"), ("a", "bar"), ("b", "foo"), ("b", "bah")], names=["lvl0", "lvl1"]
)
df = DataFrame(1, index=idx, columns=cols).sort_index().sort_index(axis=1)

mask = df[("a", "foo")] == 1
expected_mask = mask.copy()
result = df.loc[pd.IndexSlice[mask, :, ["C1", "C3"]], :]
expected = df.loc[pd.IndexSlice[:, :, ["C1", "C3"]], :]
tm.assert_frame_equal(result, expected)
tm.assert_series_equal(mask, expected_mask)


def test_loc_enlarging_with_dataframe(using_copy_on_write):
df = DataFrame({"a": [1, 2, 3]})
rhs = DataFrame({"b": [1, 2, 3], "c": [4, 5, 6]})
Expand Down

0 comments on commit a78f3db

Please sign in to comment.