Pandas: drop a level from a multi-level column index?
如果我有一个多级列索引:
1 2 | >>> cols = pd.MultiIndex.from_tuples([("a","b"), ("a","c")]) >>> pd.DataFrame([[1,2], [3,4]], columns=cols) |
1 2 3 4 5 6 | a ---+-- b | c --+---+-- 0 | 1 | 2 1 | 3 | 4 |
如何删除该索引的" a"级,所以我得到以下结果:
1 2 3 4 | b | c --+---+-- 0 | 1 | 2 1 | 3 | 4 |
您可以使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | >>> 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] |
删除索引的另一种方法是使用列表理解:
1 2 3 4 5 | df.columns = [col[1] for col in df.columns] b c 0 1 2 1 3 4 |
如果要合并两个级别的名称,例如下面的示例,其中最底层包含两个" y",则此策略也很有用:
1 2 3 4 5 6 7 | 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"。可以通过将名称与列表理解一起加入来避免这种情况。
1 2 3 4 5 | df.columns = ['_'.join(col) for col in df.columns] A_x A_y B_y 0 1 2 8 1 3 4 9 |
这是我在进行分组排序后遇到的一个问题,花了一段时间才找到另一个解决问题的方法。我在这里针对特定情况调整了该解决方案。
执行此操作的另一种方法是使用.xs方法基于
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | >>> 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 |
您也可以通过重命名列来实现:
这涉及一个手动步骤,但是可以选择,特别是如果您最终要重命名数据框。
从Pandas 0.24.0开始,我们现在可以使用DataFrame.droplevel():
1 2 3 4 5 6 7 8 | 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方法链滚动,这将非常有用。
使用
1 2 3 4 5 | df.sum(level=1,axis=1) Out[202]: b c 0 1 2 1 3 4 |
更常见的解决方案
1 2 3 4 5 6 | df.columns=df.columns.get_level_values(1) df Out[206]: b c 0 1 2 1 3 4 |
由于我不知道为什么我的droplevel()函数不起作用,所以我一直在努力解决这个问题。遍历多个,并了解表中的" a"是列名," b"," c"是索引。这样做会有所帮助
1 2 | df.columns.name = None df.reset_index() #make index become label |