Tôi đã tạo một hàm nhỏ trong câu trả lời cxrodgers , IMHO là giải pháp tốt nhất vì nó hoạt động hoàn toàn trên một chỉ mục, độc lập với bất kỳ khung hoặc chuỗi dữ liệu nào.
Có một bản sửa lỗi mà tôi đã thêm: to_frame()
phương pháp này sẽ phát minh ra các tên mới cho các cấp chỉ mục không có. Như vậy chỉ mục mới sẽ có các tên không tồn tại trong chỉ mục cũ. Tôi đã thêm một số mã để hoàn nguyên sự thay đổi tên này.
Dưới đây là đoạn mã, tôi đã tự mình sử dụng nó trong một thời gian và nó có vẻ hoạt động tốt. Nếu bạn tìm thấy bất kỳ vấn đề hoặc trường hợp khó khăn nào, tôi rất có trách nhiệm phải điều chỉnh câu trả lời của mình.
import pandas as pd
def _handle_insert_loc(loc: int, n: int) -> int:
"""
Computes the insert index from the right if loc is negative for a given size of n.
"""
return n + loc + 1 if loc < 0 else loc
def add_index_level(old_index: pd.Index, value: Any, name: str = None, loc: int = 0) -> pd.MultiIndex:
"""
Expand a (multi)index by adding a level to it.
:param old_index: The index to expand
:param name: The name of the new index level
:param value: Scalar or list-like, the values of the new index level
:param loc: Where to insert the level in the index, 0 is at the front, negative values count back from the rear end
:return: A new multi-index with the new level added
"""
loc = _handle_insert_loc(loc, len(old_index.names))
old_index_df = old_index.to_frame()
old_index_df.insert(loc, name, value)
new_index_names = list(old_index.names) # sometimes new index level names are invented when converting to a df,
new_index_names.insert(loc, name) # here the original names are reconstructed
new_index = pd.MultiIndex.from_frame(old_index_df, names=new_index_names)
return new_index
Nó đã vượt qua mã độc nhất sau:
import unittest
import numpy as np
import pandas as pd
class TestPandaStuff(unittest.TestCase):
def test_add_index_level(self):
df = pd.DataFrame(data=np.random.normal(size=(6, 3)))
i1 = add_index_level(df.index, "foo")
# it does not invent new index names where there are missing
self.assertEqual([None, None], i1.names)
# the new level values are added
self.assertTrue(np.all(i1.get_level_values(0) == "foo"))
self.assertTrue(np.all(i1.get_level_values(1) == df.index))
# it does not invent new index names where there are missing
i2 = add_index_level(i1, ["x", "y"]*3, name="xy", loc=2)
i3 = add_index_level(i2, ["a", "b", "c"]*2, name="abc", loc=-1)
self.assertEqual([None, None, "xy", "abc"], i3.names)
# the new level values are added
self.assertTrue(np.all(i3.get_level_values(0) == "foo"))
self.assertTrue(np.all(i3.get_level_values(1) == df.index))
self.assertTrue(np.all(i3.get_level_values(2) == ["x", "y"]*3))
self.assertTrue(np.all(i3.get_level_values(3) == ["a", "b", "c"]*2))
# df.index = i3
# print()
# print(df)
axis=1
, vìdf.columns
nó không có phương thức "set_index" như chỉ mục, điều này luôn khiến tôi khó chịu.