熊猫:从多级列索引中删除一个级别?

Dav*_*ver 212 python pandas

如果我有一个多级列索引:

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

如何删除该索引的"a"级别,因此我最终得到:

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

DSM*_*DSM 265

你可以使用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]
Run Code Online (Sandbox Code Playgroud)

  • 最好明确说明哪个级别被删除.从顶部开始,级别为0索引.`>>> df.columns = df.columns.droplevel(0)` (44认同)
  • @yoonghm就在那里,你可能只是在没有多索引的列上调用它 (8认同)
  • 在Panda版本0.23.4中,`df.columns.droplevel()`不再可用. (7认同)
  • 如果您尝试删除的索引位于左侧(行)而不是顶部(列)侧,则可以将"columns"更改为"index"并使用相同的方法:`>>> df.index = df .index.droplevel(1)` (5认同)

Min*_*int 55

删除索引的另一种方法是使用列表解析:

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

   b  c
0  1  2
1  3  4
Run Code Online (Sandbox Code Playgroud)

如果要组合两个级别的名称(如下面的示例中底层包含两个'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
Run Code Online (Sandbox Code Playgroud)

删除顶级会留下两列,索引为"y".通过将名称与列表理解相结合可以避免这种情况.

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

    A_x A_y B_y
0   1   2   8
1   3   4   9
Run Code Online (Sandbox Code Playgroud)

这是我在做一个小组后遇到的问题,并且花了一段时间才找到解决它的另一个问题.我在这里针对具体案例调整了解决方案.

  • `[col[1] for col in df.columns]` 更直接是 `df.columns.get_level_values(1)`。 (2认同)
  • 有类似的需求,其中某些列具有空级别值。使用以下命令:`[col [0] if col [1] ==''else col [1] for df.columns中的col]] (2认同)

spa*_*per 37

另一种方法是使用.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
Run Code Online (Sandbox Code Playgroud)

  • 这也适用于链接! (3认同)
  • 仅当整个列级别只有一个标签时,此功能才有效。 (2认同)

sed*_*deh 14

您还可以通过重命名列来实现:

df.columns = ['a', 'b']

这涉及手动步骤,但可能是一个选项,特别是如果您最终将重命名您的数据框.


WeN*_*Ben 10

一个sum 与level = 1一起使用的小技巧(当level = 1唯一时,工作)

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

更常见的解决方案 get_level_values

df.columns=df.columns.get_level_values(1)
df
Out[206]: 
   b  c
0  1  2
1  3  4
Run Code Online (Sandbox Code Playgroud)


jxc*_*jxc 10

从Pandas 0.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
Run Code Online (Sandbox Code Playgroud)

如果要保持DataFrame方法链滚动,这将非常有用。

  • `df.droplevel(0, axis='columns')` 更加明确且易于理解 (5认同)
  • 这是“最纯粹”的解决方案,因为返回一个新的 DataFrame,而不是“就地”对其进行修改。 (3认同)

小智 6

我一直在努力解决这个问题,因为我不知道为什么我的 droplevel() 函数不起作用。通过几个工作并了解表中的“a”是列名,而“b”、“c”是索引。这样做会有所帮助

df.columns.name = None
df.reset_index() #make index become label
Run Code Online (Sandbox Code Playgroud)