Skip to content

Commit 9c6771c

Browse files
proostjreback
authored andcommitted
Series.drop() with MultiIndex: inconsistent behaviour (pandas-dev#8594) (pandas-dev#30377)
1 parent aee0790 commit 9c6771c

File tree

3 files changed

+38
-3
lines changed

3 files changed

+38
-3
lines changed

doc/source/whatsnew/v1.0.0.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -789,7 +789,7 @@ MultiIndex
789789
^^^^^^^^^^
790790

791791
- Constructior for :class:`MultiIndex` verifies that the given ``sortorder`` is compatible with the actual ``lexsort_depth`` if ``verify_integrity`` parameter is ``True`` (the default) (:issue:`28735`)
792-
-
792+
- Series and MultiIndex `.drop` with `MultiIndex` raise exception if labels not in given in level (:issue:`8594`)
793793
-
794794

795795
I/O

pandas/core/indexes/multi.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -2065,7 +2065,7 @@ def drop(self, codes, level=None, errors="raise"):
20652065
dropped : MultiIndex
20662066
"""
20672067
if level is not None:
2068-
return self._drop_from_level(codes, level)
2068+
return self._drop_from_level(codes, level, errors)
20692069

20702070
if not isinstance(codes, (np.ndarray, Index)):
20712071
try:
@@ -2103,13 +2103,15 @@ def drop(self, codes, level=None, errors="raise"):
21032103

21042104
return self.delete(inds)
21052105

2106-
def _drop_from_level(self, codes, level):
2106+
def _drop_from_level(self, codes, level, errors="raise"):
21072107
codes = com.index_labels_to_array(codes)
21082108
i = self._get_level_number(level)
21092109
index = self.levels[i]
21102110
values = index.get_indexer(codes)
21112111

21122112
mask = ~algos.isin(self.codes[i], values)
2113+
if mask.all() and errors != "ignore":
2114+
raise KeyError(f"labels {codes} not found in level")
21132115

21142116
return self[mask]
21152117

pandas/tests/indexes/multi/test_drop.py

+33
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,39 @@ def test_drop_not_lexsorted():
141141
tm.assert_index_equal(lexsorted_mi.drop("a"), not_lexsorted_mi.drop("a"))
142142

143143

144+
@pytest.mark.parametrize(
145+
"msg,labels,level",
146+
[
147+
(r"labels \[4\] not found in level", 4, "a"),
148+
(r"labels \[7\] not found in level", 7, "b"),
149+
],
150+
)
151+
def test_drop_raise_exception_if_labels_not_in_level(msg, labels, level):
152+
# GH 8594
153+
mi = MultiIndex.from_arrays([[1, 2, 3], [4, 5, 6]], names=["a", "b"])
154+
s = pd.Series([10, 20, 30], index=mi)
155+
df = pd.DataFrame([10, 20, 30], index=mi)
156+
157+
with pytest.raises(KeyError, match=msg):
158+
s.drop(labels, level=level)
159+
with pytest.raises(KeyError, match=msg):
160+
df.drop(labels, level=level)
161+
162+
163+
@pytest.mark.parametrize("labels,level", [(4, "a"), (7, "b")])
164+
def test_drop_errors_ignore(labels, level):
165+
# GH 8594
166+
mi = MultiIndex.from_arrays([[1, 2, 3], [4, 5, 6]], names=["a", "b"])
167+
s = pd.Series([10, 20, 30], index=mi)
168+
df = pd.DataFrame([10, 20, 30], index=mi)
169+
170+
expected_s = s.drop(labels, level=level, errors="ignore")
171+
tm.assert_series_equal(s, expected_s)
172+
173+
expected_df = df.drop(labels, level=level, errors="ignore")
174+
tm.assert_frame_equal(df, expected_df)
175+
176+
144177
def test_drop_with_non_unique_datetime_index_and_invalid_keys():
145178
# GH 30399
146179

0 commit comments

Comments
 (0)