使用 Pandas 从查找字典中重命名多索引行

Posted

技术标签:

【中文标题】使用 Pandas 从查找字典中重命名多索引行【英文标题】:Renaming multiindex row from a look up dictionary with Pandas 【发布时间】:2021-10-12 01:42:26 【问题描述】:

鉴于当前演示文稿中显示的多级行,我想根据存储在查找字典中的信息重命名第一级索引。

目前,我有转置 df 并循环到现在的 column 名称的想法。此后,将根据存储在字典中的信息(即str_dic)检查并重命名合适的新列名。

但是,我想知道这样做是否更直接?

草拟的代码如下

import pandas as pd

def create_df (idx):
    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] )
    df = df.set_index ( [[f'idx_idx'] * len ( df )], append=True ).swaplevel ( 0 )
    # df = df.set_index ( [['temp_general'] * len ( df )], append=True ).swaplevel ( 0 )
    return df

#look up dict
str_g = ['idx_0', 'idx_1', 'idx_2', 'idx_3','idx_4']
str_h = ['E', 'b', 'c', 'd','e']
str_dic = str_g [i]: str_h [i] for i in range ( len ( str_g ) )

# create the df
all_df = [create_df ( idx ) for idx in range ( 0, len(str_h)-1)] # Delibarately minus one for worse case scenario
df = pd.concat ( all_df, axis=0 )

df=df.T
all_ls=list(df.columns.values.tolist())
for xss in all_ls:
    df=df.rename ( columns=xss: str_dic[xss[0]], level=1) #WIP

当前演示文稿

level1        
            level2        
                 A   B   C
idx_0 ONE       11  12  13
      TWO       21  22  23
      THREE     31  32  33
idx_1 ONE       11  12  13
      TWO       21  22  23
      THREE     31  32  33
idx_2 ONE       11  12  13
      TWO       21  22  23
      THREE     31  32  33
idx_3 ONE       11  12  13
      TWO       21  22  23
      THREE     31  32  33

预期输出

            level1        
            level2        
                 A   B   C
a     ONE       11  12  13
      TWO       21  22  23
      THREE     31  32  33
b     ONE       11  12  13
      TWO       21  22  23
      THREE     31  32  33
c     ONE       11  12  13
      TWO       21  22  23
      THREE     31  32  33
d     ONE       11  12  13
      TWO       21  22  23
      THREE     31  32  33

########################

奖金: 根据Anurag Dabas 的建议,我们如何根据另一个查找字典在***别附加另一个级别。

天真地,我会提出类似的建议

df.index =  pd.MultiIndex.from_product ( [s1, df.index.get_level_values ( 0 ).unique (),
                                          df.index.get_level_values ( 1 ).unique ()] )

但它返回一个错误

ValueError:长度不匹配:预期轴有 12 个元素,新值 有48个元素

基于 Anurag 修改的失败提议:

str_global=['typ1','typ1','typ2','typ2','typ3']
global_dic = str_h [i]: str_global [i] for i in range ( len ( str_h ) )
s1 = [global_dic.get ( x ) for x in df.index.get_level_values ( 0 ).unique ()]

df.index =  pd.MultiIndex.from_product ( [s1, df.index.get_level_values ( 0 ).unique (),
                                          df.index.get_level_values ( 1 ).unique ()] )

预期输出

                    A   B   C
typ1    E     ONE       11  12  13
              TWO       21  22  23
              THREE     31  32  33
typ1    b     ONE       11  12  13
              TWO       21  22  23
              THREE     31  32  33
 typ2   c     ONE       11  12  13
              TWO       21  22  23
              THREE     31  32  33
 typ2   d     ONE       11  12  13
              TWO       21  22  23
              THREE     31  32  33

【问题讨论】:

实际给出的代码输出和当前输出不一样! 你在@Xitiz 的位置。我目前正在尝试使这件事起作用。请注意WIP 【参考方案1】:

让我们尝试使用列表理解将'level 0'索引中的str_dic的键替换为它们的值,然后使用pd.MultiIndex.from_product()生成一个MultiIndex,并使用index属性将其设置为等于数据帧的索引::

s=[str_dic.get(x) for x in df.index.get_level_values(0).unique()]
df.index=pd.MultiIndex.from_product([s,df.index.get_level_values(1).unique()])

更新:

因为现在你有 4 个唯一的 level0 值和 3 个唯一的 level0 索引和 s1 中的 4 个值所以pd.MultiIndex.from_product() 创建 48 对 MultiIndex 所以在这种情况下它没有用所以使用:

s1=[global_dic.get(x) for x in df.index.get_level_values(0)]
df=df.set_index(pd.Series(s1).values,append=True)
df.index=df.index.reorder_levels([2,0,1])

df的输出:

                level1        
                level2        
                 A   B   C
E     ONE       11  12  13
      TWO       21  22  23
      THREE     31  32  33
b     ONE       11  12  13
      TWO       21  22  23
      THREE     31  32  33
c     ONE       11  12  13
      TWO       21  22  23
      THREE     31  32  33
d     ONE       11  12  13
      TWO       21  22  23
      THREE     31  32  33

【讨论】:

@balandongiv 向你们和这个很棒的社区学习...很高兴我的解决方案帮助...快乐的编码 :) 嗨@Anurag,这里有点贪心,但希望你不要介意。我想扩展您的建议,在现有级别之上附加另一个级别。根据您建议的逻辑,我重复了 2 行,但是编译器返回错误。我已经编辑并在帖子底部添加了当前发现。

以上是关于使用 Pandas 从查找字典中重命名多索引行的主要内容,如果未能解决你的问题,请参考以下文章

Pandas 多索引行和列:用匹配行中的值替换 NaN

从 Pandas 聚合中重命名结果列(“FutureWarning:不推荐使用带有重命名的字典”)

pandas 将嵌套字典转换为 mutiIndex 行和列

从命令行重命名 Github repo

在 Athena 中重命名列

在 Pandas 中重命名多个列