Python 如何使用部分指定的元组键从dict在多列索引中设置新列?

Python 如何使用部分指定的元组键从dict在多列索引中设置新列?,python,pandas,dataframe,slice,multi-index,Python,Pandas,Dataframe,Slice,Multi Index,我用以下方式初始化了一个数据帧: import pandas as pd my_multi_index = pd.MultiIndex.from_tuples([('a', 'a1'), ('a', 'a2'), ('b', 'b1'), ('b', 'b2')], names=['key1', 'key2']) df

我用以下方式初始化了一个数据帧:

import pandas as pd

my_multi_index = pd.MultiIndex.from_tuples([('a', 'a1'), ('a', 'a2'), 
                                            ('b', 'b1'), ('b', 'b2')],
                                           names=['key1', 'key2']) 
df = pd.DataFrame(data=[[1, 2], [3, 4], [5, 6], [7, 8]],
                  columns=['col1', 'col2'],
                  index=my_multi_index)
print(df)
其中:

#            col1  col2
# key1 key2            
# a    a1       1     2
#      a2       3     4
# b    b1       5     6
#      b2       7     8
# key1 key2                  
# a    a1       1     2     x
#      a2       3     4     x
# b    b1       5     6    y1
#      b2       7     8    y2
现在,我想使用部分键切片(而不是在代码中)向该数据帧添加一个新列
desc1
,我想从配置(即带有部分元组键的字典)中执行此操作:

# i'd like to externalize this and not hardcode it i.e. easier maintenance
df.loc[pd.IndexSlice['a', :], 'desc1'] = 'x'
df.loc[pd.IndexSlice['b', 'b1'], 'desc1'] = 'y1'
df.loc[pd.IndexSlice['b', 'b2'], 'desc1'] = 'y2'
print(df)
其中:

#            col1  col2
# key1 key2            
# a    a1       1     2
#      a2       3     4
# b    b1       5     6
#      b2       7     8
# key1 key2                  
# a    a1       1     2     x
#      a2       3     4     x
# b    b1       5     6    y1
#      b2       7     8    y2
请注意,设置“x”不依赖于
(“a”、“u”)
键的第二个组件,而设置“y1”和“y2”则依赖于
(“b”、“b1”)键的第二个组件。一个可能的解决方案是完全指定映射,但是如果我有一个100
(A,)
,其赋值不依赖于第二个组件,那么这也是不可取的。我希望达到上述结果,但不是硬编码切片作业,而是希望通过外部化词典实现:

我的配置字典如下所示:

my_dict = {
    ('a', None): 'x',
    ('b', 'b1'): 'y1',
    ('b', 'b2'): 'y2'
}

是否有一种pythonic和tonic的方法来使用此字典和部分指定的键来达到以前生成的切片赋值?

我们可以利用这样一个事实,即我们可以将元组作为多索引切片器进行传递。此外,我们还稍微调整了您的
my_dict
。然后我们应用一个简单的for循环:

my_dict = {
    ('a',): 'x',
    ('b', 'b1'): 'y1',
    ('b', 'b2'): 'y2'
}

for idx, value in my_dict.items():
    df.loc[idx, 'desc1'] = value

第二种选择是使用
Index.map
并在dict中填入第一个值,这样我们就可以使用
Series.ffill

my_dict = {
    ('a', 'a1'): 'x',
    ('b', 'b1'): 'y1',
    ('b', 'b2'): 'y2'
}

df['desc1'] = df.index.map(my_dict)
df['desc1'] = df['desc1'].ffill()


           col1  col2 desc1
key1 key2                  
a    a1       1     2     x
     a2       3     4     x
b    b1       5     6    y1
     b2       7     8    y2