Skip to content

Commit deec940

Browse files
ENH: specificy missing labels in loc calls GH34272 (#34912)
1 parent b8d4892 commit deec940

File tree

3 files changed

+51
-6
lines changed

3 files changed

+51
-6
lines changed

doc/source/whatsnew/v1.1.0.rst

+9
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,15 @@ including other versions of pandas.
1313
Enhancements
1414
~~~~~~~~~~~~
1515

16+
.. _whatsnew_110.specify_missing_labels:
17+
18+
KeyErrors raised by loc specify missing labels
19+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
20+
Previously, if labels were missing for a loc call, a KeyError was raised stating that this was no longer supported.
21+
22+
Now the error message also includes a list of the missing labels (max 10 items, display width 80 characters). See :issue:`34272`.
23+
24+
1625
.. _whatsnew_110.astype_string:
1726

1827
All dtypes can now be converted to ``StringDtype``

pandas/core/indexing.py

+13-6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import numpy as np
44

5+
from pandas._config.config import option_context
6+
57
from pandas._libs.indexing import _NDFrameIndexerBase
68
from pandas._libs.lib import item_from_zerodim
79
from pandas.errors import AbstractMethodError, InvalidIndexError
@@ -1283,7 +1285,8 @@ def _validate_read_indexer(
12831285
return
12841286

12851287
# Count missing values:
1286-
missing = (indexer < 0).sum()
1288+
missing_mask = indexer < 0
1289+
missing = (missing_mask).sum()
12871290

12881291
if missing:
12891292
if missing == len(indexer):
@@ -1302,11 +1305,15 @@ def _validate_read_indexer(
13021305
# code, so we want to avoid warning & then
13031306
# just raising
13041307
if not ax.is_categorical():
1305-
raise KeyError(
1306-
"Passing list-likes to .loc or [] with any missing labels "
1307-
"is no longer supported, see "
1308-
"https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#deprecate-loc-reindex-listlike" # noqa:E501
1309-
)
1308+
not_found = key[missing_mask]
1309+
1310+
with option_context("display.max_seq_items", 10, "display.width", 80):
1311+
raise KeyError(
1312+
"Passing list-likes to .loc or [] with any missing labels "
1313+
"is no longer supported. "
1314+
f"The following labels were missing: {not_found}. "
1315+
"See https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#deprecate-loc-reindex-listlike" # noqa:E501
1316+
)
13101317

13111318

13121319
@doc(IndexingMixin.iloc)

pandas/tests/indexing/test_indexing.py

+29
Original file line numberDiff line numberDiff line change
@@ -1075,3 +1075,32 @@ def test_setitem_with_bool_mask_and_values_matching_n_trues_in_length():
10751075
result = ser
10761076
expected = pd.Series([None] * 3 + list(range(5)) + [None] * 2).astype("object")
10771077
tm.assert_series_equal(result, expected)
1078+
1079+
1080+
def test_missing_labels_inside_loc_matched_in_error_message():
1081+
# GH34272
1082+
s = pd.Series({"a": 1, "b": 2, "c": 3})
1083+
error_message_regex = "missing_0.*missing_1.*missing_2"
1084+
with pytest.raises(KeyError, match=error_message_regex):
1085+
s.loc[["a", "b", "missing_0", "c", "missing_1", "missing_2"]]
1086+
1087+
1088+
def test_many_missing_labels_inside_loc_error_message_limited():
1089+
# GH34272
1090+
n = 10000
1091+
missing_labels = [f"missing_{label}" for label in range(n)]
1092+
s = pd.Series({"a": 1, "b": 2, "c": 3})
1093+
# regex checks labels between 4 and 9995 are replaced with ellipses
1094+
error_message_regex = "missing_4.*\\.\\.\\..*missing_9995"
1095+
with pytest.raises(KeyError, match=error_message_regex):
1096+
s.loc[["a", "c"] + missing_labels]
1097+
1098+
1099+
def test_long_text_missing_labels_inside_loc_error_message_limited():
1100+
# GH34272
1101+
s = pd.Series({"a": 1, "b": 2, "c": 3})
1102+
missing_labels = [f"long_missing_label_text_{i}" * 5 for i in range(3)]
1103+
# regex checks for very long labels there are new lines between each
1104+
error_message_regex = "long_missing_label_text_0.*\\\\n.*long_missing_label_text_1"
1105+
with pytest.raises(KeyError, match=error_message_regex):
1106+
s.loc[["a", "c"] + missing_labels]

0 commit comments

Comments
 (0)