Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions pandas/core/indexes/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -6865,12 +6865,15 @@ def get_slice_bound(self, label, side: Literal["left", "right"]) -> int:
# we need to look up the label
try:
slc = self.get_loc(label)
except KeyError as err:
except KeyError:
try:
return self._searchsorted_monotonic(label, side)
except ValueError:
# raise the original KeyError
raise err from None
raise KeyError(
f"Cannot get {side} slice bound for non-monotonic index "
f"with a missing label {original_label!r}. "
"Either sort the index or specify an existing label."
) from None

if isinstance(slc, np.ndarray):
# get_loc may return a boolean array, which
Expand Down
5 changes: 3 additions & 2 deletions pandas/tests/frame/indexing/test_indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -564,9 +564,10 @@ def test_getitem_setitem_integer_slice_keyerrors(self):

# non-monotonic, raise KeyError
df2 = df.iloc[list(range(5)) + list(range(5, 10))[::-1]]
with pytest.raises(KeyError, match=r"^3$"):
msg = "non-monotonic index with a missing label 3"
with pytest.raises(KeyError, match=msg):
df2.loc[3:11]
with pytest.raises(KeyError, match=r"^3$"):
with pytest.raises(KeyError, match=msg):
df2.loc[3:11] = 0

def test_fancy_getitem_slice_mixed(self, float_frame, float_string_frame):
Expand Down
5 changes: 3 additions & 2 deletions pandas/tests/indexes/numeric/test_indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -600,10 +600,11 @@ def test_slice_locs_na(self):

def test_slice_locs_na_raises(self):
index = Index([np.nan, 1, 2])
with pytest.raises(KeyError, match="1.5"):
msg = "non-monotonic index with a missing label 1.5"
with pytest.raises(KeyError, match=msg):
index.slice_locs(start=1.5)

with pytest.raises(KeyError, match="1.5"):
with pytest.raises(KeyError, match=msg):
index.slice_locs(end=1.5)


Expand Down
5 changes: 3 additions & 2 deletions pandas/tests/indexing/test_loc.py
Original file line number Diff line number Diff line change
Expand Up @@ -3162,9 +3162,10 @@ def test_loc_getitem_setitem_integer_slice_keyerrors(self):

# non-monotonic, raise KeyError
s2 = ser.iloc[list(range(5)) + list(range(9, 4, -1))]
with pytest.raises(KeyError, match=r"^3$"):
msg = "non-monotonic index with a missing label 3"
with pytest.raises(KeyError, match=msg):
s2.loc[3:11]
with pytest.raises(KeyError, match=r"^3$"):
with pytest.raises(KeyError, match=msg):
s2.loc[3:11] = 0

def test_loc_getitem_iterator(self, string_series):
Expand Down
7 changes: 7 additions & 0 deletions pandas/tests/series/indexing/test_indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,13 @@ def test_setitem_empty_indexer(indexer, val):
tm.assert_frame_equal(df, expected)


def test_loc_non_monotonic_index_with_a_missing_label():
msg = "Cannot get left slice bound for non-monotonic index with a missing label 4"
ser = Series([3, 6, 7, 6], index=[3, 8, 7, 6])
with pytest.raises(KeyError, match=msg):
ser.loc[4:7]


class TestDeprecatedIndexers:
@pytest.mark.parametrize("key", [{1}, {1: 1}])
def test_getitem_dict_and_set_deprecated(self, key):
Expand Down
Loading