Skip to content

Commit 13febab

Browse files
API: referring to duplicate level name raises ValueError (#21678)
1 parent bf583c0 commit 13febab

File tree

4 files changed

+10
-25
lines changed

4 files changed

+10
-25
lines changed

doc/source/whatsnew/v0.24.0.txt

+3
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,9 @@ Other API Changes
230230
^^^^^^^^^^^^^^^^^
231231

232232
- :class:`DatetimeIndex` now accepts :class:`Int64Index` arguments as epoch timestamps (:issue:`20997`)
233+
- Accessing a level of a ``MultiIndex`` with a duplicate name (e.g. in
234+
:meth:~MultiIndex.get_level_values) now raises a ``ValueError`` instead of
235+
a ``KeyError`` (:issue:`21678`).
233236
- Invalid construction of ``IntervalDtype`` will now always raise a ``TypeError`` rather than a ``ValueError`` if the subdtype is invalid (:issue:`21185`)
234237
- Trying to reindex a ``DataFrame`` with a non unique ``MultiIndex`` now raises a ``ValueError`` instead of an ``Exception`` (:issue:`21770`)
235238
-

pandas/core/indexes/multi.py

+6-12
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
is_categorical_dtype,
2020
is_object_dtype,
2121
is_hashable,
22+
is_integer,
2223
is_iterator,
2324
is_list_like,
2425
pandas_dtype,
@@ -757,14 +758,14 @@ def _from_elements(values, labels=None, levels=None, names=None,
757758
return MultiIndex(levels, labels, names, sortorder=sortorder)
758759

759760
def _get_level_number(self, level):
761+
count = self.names.count(level)
762+
if (count > 1) and not is_integer(level):
763+
raise ValueError('The name %s occurs multiple times, use a '
764+
'level number' % level)
760765
try:
761-
count = self.names.count(level)
762-
if count > 1:
763-
raise ValueError('The name %s occurs multiple times, use a '
764-
'level number' % level)
765766
level = self.names.index(level)
766767
except ValueError:
767-
if not isinstance(level, int):
768+
if not is_integer(level):
768769
raise KeyError('Level %s not found' % str(level))
769770
elif level < 0:
770771
level += self.nlevels
@@ -2879,13 +2880,6 @@ def isin(self, values, level=None):
28792880
else:
28802881
return np.lib.arraysetops.in1d(labs, sought_labels)
28812882

2882-
def _reference_duplicate_name(self, name):
2883-
"""
2884-
Returns True if the name refered to in self.names is duplicated.
2885-
"""
2886-
# count the times name equals an element in self.names.
2887-
return sum(name == n for n in self.names) > 1
2888-
28892883

28902884
MultiIndex._add_numeric_methods_disabled()
28912885
MultiIndex._add_numeric_methods_add_sub_disabled()

pandas/core/reshape/reshape.py

-12
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,6 @@ def __init__(self, values, index, level=-1, value_columns=None,
114114

115115
self.index = index.remove_unused_levels()
116116

117-
if isinstance(self.index, MultiIndex):
118-
if index._reference_duplicate_name(level):
119-
msg = ("Ambiguous reference to {level}. The index "
120-
"names are not unique.".format(level=level))
121-
raise ValueError(msg)
122-
123117
self.level = self.index._get_level_number(level)
124118

125119
# when index includes `nan`, need to lift levels/strides by 1
@@ -533,12 +527,6 @@ def factorize(index):
533527

534528
N, K = frame.shape
535529

536-
if isinstance(frame.columns, MultiIndex):
537-
if frame.columns._reference_duplicate_name(level):
538-
msg = ("Ambiguous reference to {level}. The column "
539-
"names are not unique.".format(level=level))
540-
raise ValueError(msg)
541-
542530
# Will also convert negative level numbers and check if out of bounds.
543531
level_num = frame.columns._get_level_number(level)
544532

pandas/tests/indexes/multi/test_unique_and_duplicates.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -255,5 +255,5 @@ def test_unique_na():
255255

256256
def test_duplicate_level_names_access_raises(idx):
257257
idx.names = ['foo', 'foo']
258-
tm.assert_raises_regex(KeyError, 'Level foo not found',
258+
tm.assert_raises_regex(ValueError, 'name foo occurs multiple times',
259259
idx._get_level_number, 'foo')

0 commit comments

Comments
 (0)