Skip to content

Commit 3dd2150

Browse files
TomAugspurgerproost
authored andcommitted
API: Restore getting name from MultiIndex level (pandas-dev#29061)
* API: Restore getting name from MultiIndex level 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 * fixups
1 parent 738b368 commit 3dd2150

File tree

8 files changed

+42
-31
lines changed

8 files changed

+42
-31
lines changed

pandas/core/indexes/multi.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -639,7 +639,10 @@ def from_frame(cls, df, sortorder=None, names=None):
639639

640640
@property
641641
def levels(self):
642-
return self._levels
642+
result = [
643+
x._shallow_copy(name=name) for x, name in zip(self._levels, self._names)
644+
]
645+
return FrozenList(result)
643646

644647
@property
645648
def _values(self):
@@ -830,7 +833,7 @@ def _set_codes(
830833
if level is None:
831834
new_codes = FrozenList(
832835
_ensure_frozen(level_codes, lev, copy=copy)._shallow_copy()
833-
for lev, level_codes in zip(self.levels, codes)
836+
for lev, level_codes in zip(self._levels, codes)
834837
)
835838
else:
836839
level = [self._get_level_number(l) for l in level]

pandas/tests/frame/test_alter_axes.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -978,7 +978,7 @@ def test_reset_index(self, float_frame):
978978
):
979979
values = lev.take(level_codes)
980980
name = names[i]
981-
tm.assert_index_equal(values, Index(deleveled[name].rename(name=None)))
981+
tm.assert_index_equal(values, Index(deleveled[name]))
982982

983983
stacked.index.names = [None, None]
984984
deleveled2 = stacked.reset_index()

pandas/tests/indexes/multi/test_constructor.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def test_constructor_single_level():
1717
levels=[["foo", "bar", "baz", "qux"]], codes=[[0, 1, 2, 3]], names=["first"]
1818
)
1919
assert isinstance(result, MultiIndex)
20-
expected = Index(["foo", "bar", "baz", "qux"])
20+
expected = Index(["foo", "bar", "baz", "qux"], name="first")
2121
tm.assert_index_equal(result.levels[0], expected)
2222
assert result.names == ["first"]
2323

@@ -292,7 +292,7 @@ def test_from_arrays_empty():
292292
# 1 level
293293
result = MultiIndex.from_arrays(arrays=[[]], names=["A"])
294294
assert isinstance(result, MultiIndex)
295-
expected = Index([])
295+
expected = Index([], name="A")
296296
tm.assert_index_equal(result.levels[0], expected)
297297
assert result.names == ["A"]
298298

@@ -440,7 +440,7 @@ def test_from_product_empty_zero_levels():
440440

441441
def test_from_product_empty_one_level():
442442
result = MultiIndex.from_product([[]], names=["A"])
443-
expected = pd.Index([])
443+
expected = pd.Index([], name="A")
444444
tm.assert_index_equal(result.levels[0], expected)
445445
assert result.names == ["A"]
446446

pandas/tests/indexes/multi/test_names.py

+15-8
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def test_index_name_retained():
2727

2828

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

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

4141
# and not on copies
42-
check_level_names(view, [None, None])
43-
check_level_names(copy, [None, None])
44-
check_level_names(shallow_copy, [None, None])
42+
check_level_names(view, ["first", "second"])
43+
check_level_names(copy, ["first", "second"])
44+
check_level_names(shallow_copy, ["first", "second"])
4545

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

5050

5151
def test_take_preserve_name(idx):
@@ -81,7 +81,7 @@ def test_names(idx, index_names):
8181
# names are assigned in setup
8282
assert index_names == ["first", "second"]
8383
level_names = [level.name for level in idx.levels]
84-
assert level_names == [None, None]
84+
assert level_names == index_names
8585

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

114114

115115
def test_duplicate_level_names_access_raises(idx):
116116
# GH19029
117117
idx.names = ["foo", "foo"]
118118
with pytest.raises(ValueError, match="name foo occurs multiple times"):
119119
idx._get_level_number("foo")
120+
121+
122+
def test_get_names_from_levels():
123+
idx = pd.MultiIndex.from_product([["a"], [1, 2]], names=["a", "b"])
124+
125+
assert idx.levels[0].name == "a"
126+
assert idx.levels[1].name == "b"

pandas/tests/indexes/multi/test_reindex.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ def test_reindex(idx):
1010
result, indexer = idx.reindex(list(idx[:4]))
1111
assert isinstance(result, MultiIndex)
1212
assert result.names == ["first", "second"]
13-
assert [level.name for level in result.levels] == [None, None]
13+
assert [level.name for level in result.levels] == ["first", "second"]
1414

1515
result, indexer = idx.reindex(list(idx))
1616
assert isinstance(result, MultiIndex)
1717
assert indexer is None
1818
assert result.names == ["first", "second"]
19-
assert [level.name for level in result.levels] == [None, None]
19+
assert [level.name for level in result.levels] == ["first", "second"]
2020

2121

2222
def test_reindex_level(idx):

pandas/tests/indexes/multi/test_reshape.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ def test_insert(idx):
1515
# key not contained in all levels
1616
new_index = idx.insert(0, ("abc", "three"))
1717

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

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

pandas/tests/reshape/test_concat.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -1219,7 +1219,7 @@ def test_concat_keys_specific_levels(self):
12191219
names=["group_key"],
12201220
)
12211221

1222-
tm.assert_index_equal(result.columns.levels[0], Index(level))
1222+
tm.assert_index_equal(result.columns.levels[0], Index(level, name="group_key"))
12231223
tm.assert_index_equal(result.columns.levels[1], Index([0, 1, 2, 3]))
12241224

12251225
assert result.columns.names == ["group_key", None]
@@ -1412,7 +1412,9 @@ def test_concat_keys_and_levels(self):
14121412
names=["first", "second"],
14131413
)
14141414
assert result.index.names == ("first", "second", None)
1415-
tm.assert_index_equal(result.index.levels[0], Index(["baz", "foo"]))
1415+
tm.assert_index_equal(
1416+
result.index.levels[0], Index(["baz", "foo"], name="first")
1417+
)
14161418

14171419
def test_concat_keys_levels_no_overlap(self):
14181420
# GH #1406

pandas/tests/test_multilevel.py

+10-11
Original file line numberDiff line numberDiff line change
@@ -975,11 +975,11 @@ def test_count(self):
975975
series.index.names = ["a", "b"]
976976

977977
result = series.count(level="b")
978-
expect = self.series.count(level=1)
978+
expect = self.series.count(level=1).rename_axis("b")
979979
tm.assert_series_equal(result, expect)
980980

981981
result = series.count(level="a")
982-
expect = self.series.count(level=0)
982+
expect = self.series.count(level=0).rename_axis("a")
983983
tm.assert_series_equal(result, expect)
984984

985985
msg = "Level x not found"
@@ -1641,16 +1641,14 @@ def test_constructor_with_tz(self):
16411641
result = MultiIndex.from_arrays([index, columns])
16421642

16431643
assert result.names == ["dt1", "dt2"]
1644-
# levels don't have names set, so set name of index/columns to None in checks
1645-
tm.assert_index_equal(result.levels[0], index.rename(name=None))
1646-
tm.assert_index_equal(result.levels[1], columns.rename(name=None))
1644+
tm.assert_index_equal(result.levels[0], index)
1645+
tm.assert_index_equal(result.levels[1], columns)
16471646

16481647
result = MultiIndex.from_arrays([Series(index), Series(columns)])
16491648

16501649
assert result.names == ["dt1", "dt2"]
1651-
# levels don't have names set, so set name of index/columns to None in checks
1652-
tm.assert_index_equal(result.levels[0], index.rename(name=None))
1653-
tm.assert_index_equal(result.levels[1], columns.rename(name=None))
1650+
tm.assert_index_equal(result.levels[0], index)
1651+
tm.assert_index_equal(result.levels[1], columns)
16541652

16551653
def test_set_index_datetime(self):
16561654
# GH 3950
@@ -1672,17 +1670,18 @@ def test_set_index_datetime(self):
16721670
df.index = df.index.tz_convert("US/Pacific")
16731671

16741672
expected = pd.DatetimeIndex(
1675-
["2011-07-19 07:00:00", "2011-07-19 08:00:00", "2011-07-19 09:00:00"]
1673+
["2011-07-19 07:00:00", "2011-07-19 08:00:00", "2011-07-19 09:00:00"],
1674+
name="datetime",
16761675
)
16771676
expected = expected.tz_localize("UTC").tz_convert("US/Pacific")
16781677

16791678
df = df.set_index("label", append=True)
16801679
tm.assert_index_equal(df.index.levels[0], expected)
1681-
tm.assert_index_equal(df.index.levels[1], Index(["a", "b"]))
1680+
tm.assert_index_equal(df.index.levels[1], Index(["a", "b"], name="label"))
16821681
assert df.index.names == ["datetime", "label"]
16831682

16841683
df = df.swaplevel(0, 1)
1685-
tm.assert_index_equal(df.index.levels[0], Index(["a", "b"]))
1684+
tm.assert_index_equal(df.index.levels[0], Index(["a", "b"], name="label"))
16861685
tm.assert_index_equal(df.index.levels[1], expected)
16871686
assert df.index.names == ["label", "datetime"]
16881687

0 commit comments

Comments
 (0)