使用 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 从查找字典中重命名多索引行的主要内容,如果未能解决你的问题,请参考以下文章