From e1c9b6ec963ecf9b5e693b937679964097f2d500 Mon Sep 17 00:00:00 2001 From: Roman Imankulov Date: Thu, 25 Oct 2018 12:33:41 +0100 Subject: [PATCH] BUG: Let MultiIndex.set_levels accept any iterable (#23273) (#23291) --- doc/source/whatsnew/v0.24.0.txt | 1 + pandas/core/indexes/multi.py | 3 +++ pandas/tests/indexes/multi/test_get_set.py | 14 ++++++++++++++ 3 files changed, 18 insertions(+) diff --git a/doc/source/whatsnew/v0.24.0.txt b/doc/source/whatsnew/v0.24.0.txt index 5a903db4a52efc..a45100b7a827e9 100644 --- a/doc/source/whatsnew/v0.24.0.txt +++ b/doc/source/whatsnew/v0.24.0.txt @@ -1092,6 +1092,7 @@ Indexing - Bug in :meth:`DataFrame.loc` when indexing with an :class:`IntervalIndex` (:issue:`19977`) - :class:`Index` no longer mangles ``None``, ``NaN`` and ``NaT``, i.e. they are treated as three different keys. However, for numeric Index all three are still coerced to a ``NaN`` (:issue:`22332`) - Bug in `scalar in Index` if scalar is a float while the ``Index`` is of integer dtype (:issue:`22085`) +- Bug in `MultiIndex.set_levels` when levels value is not subscriptable (:issue:`23273`) Missing ^^^^^^^ diff --git a/pandas/core/indexes/multi.py b/pandas/core/indexes/multi.py index 3cccb655033781..79ac32d2f6a0b1 100644 --- a/pandas/core/indexes/multi.py +++ b/pandas/core/indexes/multi.py @@ -389,6 +389,9 @@ def set_levels(self, levels, level=None, inplace=False, labels=[[0, 0, 1, 1], [0, 1, 0, 1]], names=[u'foo', u'bar']) """ + if is_list_like(levels) and not isinstance(levels, Index): + levels = list(levels) + if level is not None and not is_list_like(level): if not is_list_like(levels): raise TypeError("Levels must be list-like") diff --git a/pandas/tests/indexes/multi/test_get_set.py b/pandas/tests/indexes/multi/test_get_set.py index 99ab54a83636c9..ff2170839b012b 100644 --- a/pandas/tests/indexes/multi/test_get_set.py +++ b/pandas/tests/indexes/multi/test_get_set.py @@ -414,3 +414,17 @@ def test_set_value_keeps_names(): df.at[('grethe', '4'), 'one'] = 99.34 assert df._is_copy is None assert df.index.names == ('Name', 'Number') + + +def test_set_levels_with_iterable(): + # GH23273 + sizes = [1, 2, 3] + colors = ['black'] * 3 + index = pd.MultiIndex.from_arrays([sizes, colors], names=['size', 'color']) + + result = index.set_levels(map(int, ['3', '2', '1']), level='size') + + expected_sizes = [3, 2, 1] + expected = pd.MultiIndex.from_arrays([expected_sizes, colors], + names=['size', 'color']) + tm.assert_index_equal(result, expected)