Skip to content

Commit 322f5dd

Browse files
committed
BUG: raise when wrong level name is passed to "unstack"
closes pandas-dev#18303
1 parent 61362be commit 322f5dd

File tree

4 files changed

+25
-2
lines changed

4 files changed

+25
-2
lines changed

doc/source/whatsnew/v0.25.1.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ Groupby/resample/rolling
128128
Reshaping
129129
^^^^^^^^^
130130

131-
-
131+
- A ``KeyError`` is now raised if ``.unstack()`` is called on a flat :class:`Index` passing a name which is not the correct one (:issue:`18303`)
132132
-
133133
-
134134

pandas/core/indexes/base.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -1524,7 +1524,9 @@ def _validate_index_level(self, level):
15241524
"Too many levels:" " Index has only 1 level, not %d" % (level + 1)
15251525
)
15261526
elif level != self.name:
1527-
raise KeyError("Level %s must be same as name (%s)" % (level, self.name))
1527+
raise KeyError(
1528+
'Level ("%s") is different from index name ("%s")' % (level, self.name)
1529+
)
15281530

15291531
def _get_level_number(self, level):
15301532
self._validate_index_level(level)

pandas/core/reshape/reshape.py

+5
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
ensure_platform_int,
1313
is_bool_dtype,
1414
is_extension_array_dtype,
15+
is_integer,
1516
is_integer_dtype,
1617
is_list_like,
1718
is_object_dtype,
@@ -402,6 +403,10 @@ def unstack(obj, level, fill_value=None):
402403
else:
403404
level = level[0]
404405

406+
# Prioritize integer interpretation (GH #21677):
407+
if not is_integer(level) and not level == "__placeholder__":
408+
level = obj.index._get_level_number(level)
409+
405410
if isinstance(obj, DataFrame):
406411
if isinstance(obj.index, MultiIndex):
407412
return _unstack_frame(obj, level, fill_value=fill_value)

pandas/tests/test_multilevel.py

+16
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,22 @@ def test_stack_unstack_preserve_names(self):
524524
restacked = unstacked.stack()
525525
assert restacked.index.names == self.frame.index.names
526526

527+
@pytest.mark.parametrize("method", ['stack', 'unstack'])
528+
def test_stack_unstack_wrong_level_name(self, method):
529+
# GH 18303 - wrong level name should raise
530+
531+
# A DataFrame with flat axes:
532+
df = self.frame.loc['foo']
533+
534+
with pytest.raises(KeyError, match="is different from index name"):
535+
getattr(df, method)('mistake')
536+
537+
if method == 'unstack':
538+
# Same on a Series:
539+
s = df.iloc[:, 0]
540+
with pytest.raises(KeyError, match="is different from index name"):
541+
getattr(s, method)('mistake')
542+
527543
def test_unstack_level_name(self):
528544
result = self.frame.unstack("second")
529545
expected = self.frame.unstack(level=1)

0 commit comments

Comments
 (0)