Skip to content

BUG: Should not raises errors in .set_names and comparison methods for MultiIndex with nlevels == 1 (GH21149) #21182

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 8 commits into from
2 changes: 2 additions & 0 deletions doc/source/whatsnew/v0.23.1.txt
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ Indexing

- Bug in :meth:`Series.reset_index` where appropriate error was not raised with an invalid level name (:issue:`20925`)
- Bug in :func:`interval_range` when ``start``/``periods`` or ``end``/``periods`` are specified with float ``start`` or ``end`` (:issue:`21161`)
- Bug in :meth:`MultiIndex.set_names` where error was raised for a MultiIndex with self.nlevels == 1 (:issue: `21149`)
- Bug in comparison operations for :class:`MultiIndex` where error was raised on equality / inequality comparison involving a MultiIndex with self.nlevels == 1 (:issue: `21149`)
-

I/O
Expand Down
13 changes: 8 additions & 5 deletions pandas/core/indexes/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,13 @@ def cmp_method(self, other):
if needs_i8_conversion(self) and needs_i8_conversion(other):
return self._evaluate_compare(other, op)

from .multi import MultiIndex
if is_object_dtype(self) and self.nlevels == 1:
# don't pass MultiIndex
with np.errstate(all='ignore'):
result = ops._comp_method_OBJECT_ARRAY(op, self.values, other)
if not isinstance(self, MultiIndex):
# don't pass MultiIndex
with np.errstate(all='ignore'):
result = ops._comp_method_OBJECT_ARRAY(op,
self.values, other)

else:

Expand Down Expand Up @@ -1383,8 +1386,8 @@ def set_names(self, names, level=None, inplace=False):
labels=[[0, 0, 1, 1], [0, 1, 0, 1]],
names=[u'baz', u'bar'])
"""

if level is not None and self.nlevels == 1:
from .multi import MultiIndex
if level is not None and not isinstance(self, MultiIndex):
raise ValueError('Level must be None for non-MultiIndex')

if level is not None and not is_list_like(level) and is_list_like(
Expand Down
34 changes: 34 additions & 0 deletions pandas/tests/indexes/test_multi.py
Original file line number Diff line number Diff line change
Expand Up @@ -3291,3 +3291,37 @@ def test_duplicate_multiindex_labels(self):
with pytest.raises(ValueError):
ind.set_levels([['A', 'B', 'A', 'A', 'B'], [2, 1, 3, -2, 5]],
inplace=True)

testdata = [
(pd.MultiIndex.from_product([[0, 1], [1, 0]]), pd.Series(range(4)), 4),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't create a variable here, just put it directly in the parametrize (see how to format it from other tests)

(pd.MultiIndex.from_product([[0, 1]]), pd.Series(range(2)), 2),
]

@pytest.mark.parametrize("midx,idx,count", testdata)
def test_multiindex_compare(self, midx, idx, count):
# GH 21149 - change in 'def cmp_method()'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a non-sensical comment, be more descriptive.

expected = pd.Series([True]).repeat(count)
expected.reset_index(drop=True, inplace=True)
result = pd.Series(midx == midx)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not really clear what you are testing, this is way too dense. put blank lines and a comment in between cases.

tm.assert_series_equal(result, expected)
result = (idx == idx)
tm.assert_series_equal(result, expected)

expected = pd.Series([False]).repeat(count)
expected.reset_index(drop=True, inplace=True)
result = pd.Series(midx > midx)
tm.assert_series_equal(result, expected)
result = pd.Series(midx == idx)
tm.assert_series_equal(result, expected)

with tm.assert_raises_regex(TypeError, 'not supported'):
midx > idx

def test_multiindex_set_names(self):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

put this near the other tests for set_names

# GH 21149 - change in 'def set_names()'
result = pd.MultiIndex.from_product([[0, 1]])
result.set_names('first', level=0, inplace=True)
expected = pd.MultiIndex(levels=[[0, 1]],
labels=[[0, 1]],
names=['first'])
tm.assert_index_equal(result, expected)