首页 > 解决方案 > 如何从多索引列数据框创建多级索引

问题描述

主要目标是从现有的df.

假设我们有如下多级列

        level1            
        level2            
      sub_name   A   B   C
ONE         TT  11  12  13
TWO         TT  21  22  23
THREE       TT  31  32  33

然后,预期的输出 (1)

           level1        
           level2        
           A   B   C
TT ONE       11  12  13
   TWO       21  22  23
   THREE     31  32  33

我觉得这可以通过groupOR 直接使用来实现set_index,如下所示

df = df.groupby((slice ( None ), slice ( None ),'sub_name'),as_index = False)

或者

df=df.set_index([(slice ( None ), slice ( None ),'sub_name')])

但是,这是行不通的。

这样第一种方法返回错误

TypeError:不可散列的类型:'sl​​ice'

第二种方法

TypeError:参数“keys”可能是列键、一维数组或仅包含有效列键和一维数组的列表。接收到的列类型为 <class 'tuple'>

我可以知道实现预期目标的正确方法是什么。

重现上述错误的完整代码

import pandas as pd

df = pd.DataFrame ( {'A': [11, 21, 31],
                     'B': [12, 22, 32],
                     'C': [13, 23, 33]},
                    index=['ONE', 'TWO', 'THREE'] )

df.columns = pd.MultiIndex.from_product ( [['level1'], ['level2'], df.columns] )

df2 = pd.DataFrame ( ['TT'] * len ( df ), index=df.index,
                     columns=pd.MultiIndex.from_product ( [df.columns.levels [0],
                                                           df.columns.levels [1],
                                                           ['sub_name']] ) ) 
# Im just curios whether there is simpler way of creating constant column like this


df = pd.concat ( [df2,df ], axis=1 )

# df = df.groupby((slice ( None ), slice ( None ),'sub_name'),as_index = False)

# df=df.set_index([(slice ( None ), slice ( None ),'sub_name')])

贡献者的支持下。

额外的问题是是否可以TT在不需要创建常量列的情况下添加另一个级别(即df2

               level1
               level2
               A   B   C
main_level TT  ONE     11  12  13
               TWO     21  22  23
               THREE   31  32  33

标签: pythonpandasindexing

解决方案


你可以试试set_index()++++ xs()swaplevel()drop()

df=(df.set_index(df.xs('sub_name',axis=1,level=2).values.squeeze(),append=True)
      .swaplevel(0).drop('sub_name',axis=1,level=2))

输出:

            level1
            level2
            A   B   C
TT  ONE     11  12  13
    TWO     21  22  23
    THREE   31  32  33

注意:您也可以使用df.loc[:,(slice(None),slice(None),'sub_name')]代替df.xs('sub_name',axis=1,level=2)

更新:

你可以试试pd.MultiIndex.from_product()

df.index=pd.MultiIndex.from_product([['main_level'],['TT'],df.index.unique()])

输出:

                        level1
                        level2
                        A   B   C
main_level TT   ONE     11  12  13
                TWO     21  22  23
                THREE   31  32  33

推荐阅读