ฉันสร้างฟังก์ชั่นเล็กน้อยจากคำตอบของcxrodgersซึ่ง IMHO เป็นทางออกที่ดีที่สุดเนื่องจากทำงานบนดัชนีเท่านั้นโดยไม่ขึ้นอยู่กับกรอบข้อมูลหรือชุดข้อมูลใด ๆ
มีการแก้ไขอย่างหนึ่งที่ฉันเพิ่ม: to_frame()
เมธอดจะสร้างชื่อใหม่สำหรับระดับดัชนีที่ไม่มี ดังนั้นดัชนีใหม่จะมีชื่อที่ไม่มีอยู่ในดัชนีเก่า ฉันได้เพิ่มรหัสเพื่อยกเลิกการเปลี่ยนชื่อนี้
ด้านล่างนี้คือรหัสที่ฉันใช้เองมาระยะหนึ่งแล้วและดูเหมือนว่าจะใช้งานได้ดี หากคุณพบปัญหาใด ๆ หรือกรณีที่จำเป็นฉันมีความจำเป็นอย่างมากที่จะต้องปรับเปลี่ยนคำตอบของฉัน
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)
new_index_names.insert(loc, name)
new_index = pd.MultiIndex.from_frame(old_index_df, names=new_index_names)
return new_index
ผ่านรหัสที่ไม่เหมาะสมต่อไปนี้:
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")
self.assertEqual([None, None], i1.names)
self.assertTrue(np.all(i1.get_level_values(0) == "foo"))
self.assertTrue(np.all(i1.get_level_values(1) == df.index))
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)
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))
axis=1
เนื่องจากdf.columns
ไม่มีเมธอด "set_index" เหมือนดัชนีซึ่งมักจะทำให้ฉันสับสน