在pandas MultiIndex前添加一层级别

197 投票
6 回答
145420 浏览
提问于 2025-04-17 15:03

我有一个数据框(DataFrame),它的索引是多层的,这个多层索引是在进行一些分组后创建的:

import numpy as np
import pandas as pd
from numpy.random import randn

df = pd.DataFrame({'A' : ['a1', 'a1', 'a2', 'a3'], 
                   'B' : ['b1', 'b2', 'b3', 'b4'], 
                   'Vals' : randn(4)}
                 ).groupby(['A', 'B']).sum()

#            Vals
# A  B           
# a1 b1 -1.632460
#    b2  0.596027
# a2 b3 -0.619130
# a3 b4 -0.002009

我想在这个多层索引的前面加一个新的层级,让它变成像下面这样的样子:

#                       Vals
# FirstLevel A  B           
# Foo        a1 b1 -1.632460
#               b2  0.596027
#            a2 b3 -0.619130
#            a3 b4 -0.002009

6 个回答

60

我觉得这是一个更通用的解决方案:

# Convert index to dataframe
old_idx = df.index.to_frame()

# Insert new level at specified location
old_idx.insert(0, 'new_level_name', new_level_values)

# Convert back to MultiIndex
df.index = pandas.MultiIndex.from_frame(old_idx)

相比其他答案,这个方法有一些优点:

  • 你可以在任何位置添加新的层级,而不仅仅是最上面。
  • 这个方法只是对索引进行操作,不需要像拼接那样去处理数据。
  • 它不需要添加一个额外的列作为中间步骤,这样可以避免破坏多层列索引。
178

你可以先把它作为一个普通的列添加,然后再把它加到当前的索引上,像这样:

df['Firstlevel'] = 'Foo'
df.set_index('Firstlevel', append=True, inplace=True)

如果需要的话,可以用下面的代码来改变顺序:

df.reorder_levels(['Firstlevel', 'A', 'B'])

这样就会得到:

                      Vals
Firstlevel A  B           
Foo        a1 b1  0.871563
              b2  0.494001
           a2 b3 -0.167811
           a3 b4 -1.353409

编辑

还有一个更简短的解决方案(省去了重新排序的步骤):

df['Firstlevel'] = 'Foo'
df.set_index(['Firstlevel', df.index], inplace=True)

或者你也可以这样做(使用 axis=1 来处理列):

df = pd.concat([df], keys=["Firstlevel"], axis=0)
261

pandas.concat() 这个方法,可以很简单地在一行代码里完成这个操作:

import pandas as pd

pd.concat([df], keys=['Foo'], names=['Firstlevel'])

还有一种更简短的方法:

pd.concat({'Foo': df}, names=['Firstlevel'])

这个方法可以应用到很多数据框上,详细信息可以查看 文档

撰写回答