From ee3204c862538e5adc95e1921c18b4cc9db7e33a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moritz=20M=C3=BCnst?= Date: Wed, 3 Jan 2018 17:55:47 +0100 Subject: [PATCH 1/5] Fix #19057 --- pandas/core/indexes/multi.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pandas/core/indexes/multi.py b/pandas/core/indexes/multi.py index 7107378671ba5..398ee7d0aef3c 100644 --- a/pandas/core/indexes/multi.py +++ b/pandas/core/indexes/multi.py @@ -328,8 +328,9 @@ def _set_labels(self, labels, level=None, copy=False, validate=True, else: level = [self._get_level_number(l) for l in level] new_labels = list(self._labels) - for l, lev, lab in zip(level, self.levels, labels): - new_labels[l] = _ensure_frozen( + for lev_idx, lab in zip(level, labels): + lev = self.levels[lev_idx] + new_labels[lev_idx] = _ensure_frozen( lab, lev, copy=copy)._shallow_copy() new_labels = FrozenList(new_labels) From caf1a65147f2efd90689e10f41f6e41c8bf45ffa Mon Sep 17 00:00:00 2001 From: Moritz Muenst Date: Fri, 5 Jan 2018 11:33:11 +0100 Subject: [PATCH 2/5] Test set_labels for distinctly sized index levels --- pandas/tests/indexes/test_multi.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/pandas/tests/indexes/test_multi.py b/pandas/tests/indexes/test_multi.py index 2a7c020f4c9e9..02ae611f4c43a 100644 --- a/pandas/tests/indexes/test_multi.py +++ b/pandas/tests/indexes/test_multi.py @@ -327,6 +327,28 @@ def assert_matching(actual, expected): assert_matching(ind2.labels, new_labels) assert_matching(self.index.labels, labels) + def test_set_label_distinctly_sized_levels(self): + # label changing for levels of different magnitude of categories + def assert_equal(actual, expected): + assert len(actual) == len(expected) + for act, exp in zip(actual, expected): + act = np.asarray(act) + exp = np.asarray(exp) + tm.assert_numpy_array_equal(act, exp, check_dtype=True) + + ind = pd.MultiIndex.from_tuples([(0, i) for i in range(130)]) + new_labels = range(129, -1, -1) + ind_reference = pd.MultiIndex.from_tuples( + [(0, i) for i in new_labels]) + + # [w/o mutation] + ind2 = ind.set_labels(labels=new_labels, level=1) + assert_equal(ind2, ind_reference) + + # [w/ mutation] + ind.set_labels(labels=new_labels, level=1, inplace=True) + assert_equal(ind, ind_reference) + def test_set_levels_labels_names_bad_input(self): levels, labels = self.index.levels, self.index.labels names = self.index.names From 3c79f35746faf4b45efedd24883b77b687c4a306 Mon Sep 17 00:00:00 2001 From: Moritz Muenst Date: Fri, 5 Jan 2018 12:54:28 +0100 Subject: [PATCH 3/5] Add whatsnew entry --- doc/source/whatsnew/v0.23.0.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/whatsnew/v0.23.0.txt b/doc/source/whatsnew/v0.23.0.txt index 6a48abb6c6592..4f383683b5ca5 100644 --- a/doc/source/whatsnew/v0.23.0.txt +++ b/doc/source/whatsnew/v0.23.0.txt @@ -325,6 +325,7 @@ Indexing - Bug in indexing non-scalar value from ``Series`` having non-unique ``Index`` will return value flattened (:issue:`17610`) - Bug in :func:`DatetimeIndex.insert` where inserting ``NaT`` into a timezone-aware index incorrectly raised (:issue:`16357`) - Bug in ``__setitem__`` when indexing a :class:`DataFrame` with a 2-d boolean ndarray (:issue:`18582`) +- Bug in :func:`MultiIndex.set_labels` which would cause casting (and potentially clipping) of the new labels if the ``level`` argument is not 0 or a list like [0, 1, ... ] (:issue:`19057`) I/O From 2ad4fa9454d35898d8bc35e9976b9307d9606134 Mon Sep 17 00:00:00 2001 From: Moritz Muenst Date: Fri, 5 Jan 2018 15:15:28 +0100 Subject: [PATCH 4/5] Simplify added test code --- pandas/tests/indexes/test_multi.py | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/pandas/tests/indexes/test_multi.py b/pandas/tests/indexes/test_multi.py index 02ae611f4c43a..9664d73651185 100644 --- a/pandas/tests/indexes/test_multi.py +++ b/pandas/tests/indexes/test_multi.py @@ -327,27 +327,20 @@ def assert_matching(actual, expected): assert_matching(ind2.labels, new_labels) assert_matching(self.index.labels, labels) - def test_set_label_distinctly_sized_levels(self): # label changing for levels of different magnitude of categories - def assert_equal(actual, expected): - assert len(actual) == len(expected) - for act, exp in zip(actual, expected): - act = np.asarray(act) - exp = np.asarray(exp) - tm.assert_numpy_array_equal(act, exp, check_dtype=True) - ind = pd.MultiIndex.from_tuples([(0, i) for i in range(130)]) new_labels = range(129, -1, -1) - ind_reference = pd.MultiIndex.from_tuples( + expected = pd.MultiIndex.from_tuples( [(0, i) for i in new_labels]) - # [w/o mutation] - ind2 = ind.set_labels(labels=new_labels, level=1) - assert_equal(ind2, ind_reference) + # [w/o mutation] + result = ind.set_labels(labels=new_labels, level=1) + assert result.equals(expected) - # [w/ mutation] - ind.set_labels(labels=new_labels, level=1, inplace=True) - assert_equal(ind, ind_reference) + # [w/ mutation] + result = ind.copy() + result.set_labels(labels=new_labels, level=1, inplace=True) + assert result.equals(expected) def test_set_levels_labels_names_bad_input(self): levels, labels = self.index.levels, self.index.labels From 48fb84306bd141e8414c927656e9653a8ee1b79d Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Fri, 5 Jan 2018 16:21:28 -0600 Subject: [PATCH 5/5] CI: Trigger CI with empty commit