Skip to content

Commit

Permalink
API: Restore getting name from MultiIndex level
Browse files Browse the repository at this point in the history
xref https://issues.apache.org/jira/browse/ARROW-6922 /
pandas-dev#27242 (comment)
/ pandas-dev#29032

No docs yet, since it isn't clear how this will eventually sort out. But
we at least want to preserve this behavior for 1.0
  • Loading branch information
TomAugspurger committed Oct 17, 2019
1 parent 509eb14 commit 0362522
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 17 deletions.
7 changes: 5 additions & 2 deletions pandas/core/indexes/multi.py
Original file line number Diff line number Diff line change
Expand Up @@ -639,7 +639,10 @@ def from_frame(cls, df, sortorder=None, names=None):

@property
def levels(self):
return self._levels
result = [
x._shallow_copy(name=name) for x, name in zip(self._levels, self._names)
]
return FrozenList(result)

@property
def _values(self):
Expand Down Expand Up @@ -830,7 +833,7 @@ def _set_codes(
if level is None:
new_codes = FrozenList(
_ensure_frozen(level_codes, lev, copy=copy)._shallow_copy()
for lev, level_codes in zip(self.levels, codes)
for lev, level_codes in zip(self._levels, codes)
)
else:
level = [self._get_level_number(l) for l in level]
Expand Down
6 changes: 3 additions & 3 deletions pandas/tests/indexes/multi/test_constructor.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def test_constructor_single_level():
levels=[["foo", "bar", "baz", "qux"]], codes=[[0, 1, 2, 3]], names=["first"]
)
assert isinstance(result, MultiIndex)
expected = Index(["foo", "bar", "baz", "qux"])
expected = Index(["foo", "bar", "baz", "qux"], name="first")
tm.assert_index_equal(result.levels[0], expected)
assert result.names == ["first"]

Expand Down Expand Up @@ -292,7 +292,7 @@ def test_from_arrays_empty():
# 1 level
result = MultiIndex.from_arrays(arrays=[[]], names=["A"])
assert isinstance(result, MultiIndex)
expected = Index([])
expected = Index([], name="A")
tm.assert_index_equal(result.levels[0], expected)
assert result.names == ["A"]

Expand Down Expand Up @@ -440,7 +440,7 @@ def test_from_product_empty_zero_levels():

def test_from_product_empty_one_level():
result = MultiIndex.from_product([[]], names=["A"])
expected = pd.Index([])
expected = pd.Index([], name="A")
tm.assert_index_equal(result.levels[0], expected)
assert result.names == ["A"]

Expand Down
23 changes: 15 additions & 8 deletions pandas/tests/indexes/multi/test_names.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def test_index_name_retained():


def test_changing_names(idx):
assert [level.name for level in idx.levels] == [None, None]
assert [level.name for level in idx.levels] == ["first", "second"]

view = idx.view()
copy = idx.copy()
Expand All @@ -36,16 +36,16 @@ def test_changing_names(idx):
# changing names should not change level names on object
new_names = [name + "a" for name in idx.names]
idx.names = new_names
check_level_names(idx, [None, None])
check_level_names(idx, ["firsta", "seconda"])

# and not on copies
check_level_names(view, [None, None])
check_level_names(copy, [None, None])
check_level_names(shallow_copy, [None, None])
check_level_names(view, ["first", "second"])
check_level_names(copy, ["first", "second"])
check_level_names(shallow_copy, ["first", "second"])

# and copies shouldn't change original
shallow_copy.names = [name + "c" for name in shallow_copy.names]
check_level_names(idx, [None, None])
check_level_names(idx, ["firsta", "seconda"])


def test_take_preserve_name(idx):
Expand Down Expand Up @@ -81,7 +81,7 @@ def test_names(idx, index_names):
# names are assigned in setup
assert index_names == ["first", "second"]
level_names = [level.name for level in idx.levels]
assert level_names == [None, None]
assert level_names == index_names

# setting bad names on existing
index = idx
Expand Down Expand Up @@ -109,11 +109,18 @@ def test_names(idx, index_names):
# names are assigned on index, but not transferred to the levels
index.names = ["a", "b"]
level_names = [level.name for level in index.levels]
assert level_names == [None, None]
assert level_names == ["a", "b"]


def test_duplicate_level_names_access_raises(idx):
# GH19029
idx.names = ["foo", "foo"]
with pytest.raises(ValueError, match="name foo occurs multiple times"):
idx._get_level_number("foo")


def test_get_names_from_levels():
idx = pd.MultiIndex.from_product([["a"], [1, 2]], names=["a", "b"])

assert idx.levels[0].name == "a"
assert idx.levels[1].name == "b"
4 changes: 2 additions & 2 deletions pandas/tests/indexes/multi/test_reindex.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ def test_reindex(idx):
result, indexer = idx.reindex(list(idx[:4]))
assert isinstance(result, MultiIndex)
assert result.names == ["first", "second"]
assert [level.name for level in result.levels] == [None, None]
assert [level.name for level in result.levels] == ["first", "second"]

result, indexer = idx.reindex(list(idx))
assert isinstance(result, MultiIndex)
assert indexer is None
assert result.names == ["first", "second"]
assert [level.name for level in result.levels] == [None, None]
assert [level.name for level in result.levels] == ["first", "second"]


def test_reindex_level(idx):
Expand Down
4 changes: 2 additions & 2 deletions pandas/tests/indexes/multi/test_reshape.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ def test_insert(idx):
# key not contained in all levels
new_index = idx.insert(0, ("abc", "three"))

exp0 = Index(list(idx.levels[0]) + ["abc"])
exp0 = Index(list(idx.levels[0]) + ["abc"], name="first")
tm.assert_index_equal(new_index.levels[0], exp0)
assert new_index.names == ["first", "second"]

exp1 = Index(list(idx.levels[1]) + ["three"])
exp1 = Index(list(idx.levels[1]) + ["three"], name="second")
tm.assert_index_equal(new_index.levels[1], exp1)
assert new_index[0] == ("abc", "three")

Expand Down

0 comments on commit 0362522

Please sign in to comment.