Pandas: 如何从多层列索引中删除一个级别?

402 投票
8 回答
465419 浏览
提问于 2025-04-17 21:10

如果我有一个多层的列索引:

>>> cols = pd.MultiIndex.from_tuples([("a", "b"), ("a", "c")])
>>> pd.DataFrame([[1,2], [3,4]], columns=cols)
    a
   ---+--
    b | c
--+---+--
0 | 1 | 2
1 | 3 | 4

我该怎么去掉这个索引中的“a”层级,这样我最后得到的结果是:

    b | c
--+---+--
0 | 1 | 2
1 | 3 | 4

8 个回答

20

这是一个小技巧,使用了 sum 函数,当你设置的级别(level)为1时,这个方法有效,前提是所有的值都是独一无二的。

df.sum(level=1,axis=1)
Out[202]: 
   b  c
0  1  2
1  3  4

更常见的解决办法是使用 get_level_values

df.columns=df.columns.get_level_values(1)
df
Out[206]: 
   b  c
0  1  2
1  3  4
54

另一种方法是使用 .xs 方法,根据 df 的一个交叉部分来重新赋值 df

>>> df

    a
    b   c
0   1   2
1   3   4

>>> df = df.xs('a', axis=1, drop_level=True)

    # 'a' : key on which to get cross section
    # axis=1 : get cross section of column
    # drop_level=True : returns cross section without the multilevel index

>>> df

    b   c
0   1   2
1   3   4
111

另一种去掉索引的方法是使用列表推导式:

df.columns = [col[1] for col in df.columns]

   b  c
0  1  2
1  3  4

这种方法也很有用,特别是当你想把两个层级的名字结合在一起时,就像下面的例子,其中底层有两个'y':

cols = pd.MultiIndex.from_tuples([("A", "x"), ("A", "y"), ("B", "y")])
df = pd.DataFrame([[1,2, 8 ], [3,4, 9]], columns=cols)

   A     B
   x  y  y
0  1  2  8
1  3  4  9

如果去掉顶层,就会留下两个索引为'y'的列。通过使用列表推导式,可以避免这个问题,直接把名字连接起来。

df.columns = ['_'.join(col) for col in df.columns]

    A_x A_y B_y
0   1   2   8
1   3   4   9

这是我在做分组操作后遇到的问题,花了不少时间才找到 这个其他问题,它解决了我的困扰。我把那个解决方案调整到这里的具体情况。

133

从Pandas0.24.0版本开始,我们可以使用DataFrame.droplevel()这个功能:

cols = pd.MultiIndex.from_tuples([("a", "b"), ("a", "c")])
df = pd.DataFrame([[1,2], [3,4]], columns=cols)

df.droplevel(0, axis=1) 

#   b  c
#0  1  2
#1  3  4

这个功能非常有用,特别是当你想要继续使用DataFrame的方法链时。

476

你可以使用 MultiIndex.droplevel 这个功能:

>>> cols = pd.MultiIndex.from_tuples([("a", "b"), ("a", "c")])
>>> df = pd.DataFrame([[1,2], [3,4]], columns=cols)
>>> df
   a   
   b  c
0  1  2
1  3  4

[2 rows x 2 columns]
>>> df.columns = df.columns.droplevel()
>>> df
   b  c
0  1  2
1  3  4

[2 rows x 2 columns]

撰写回答