我有一个带有列multiindex的数据框,我需要对其进行切片并在切片之间执行数学运算。
# sample df
idx=pd.IndexSlice
np.random.seed(123)
tuples = list(zip(*[['one', 'one', 'two', 'two', 'three', 'three'],['foo', 'bar', 'foo', 'bar', 'foo', 'bar']]))
index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])
df = pd.DataFrame(np.random.randn(3, 6), index=['A', 'B', 'C'], columns=index)
如果我想在各个列之间执行加/减操作,则可以使用索引切片并按以下方式进行操作:
df.loc[:,idx['three','foo']] - df.loc[:,idx['two','foo']]
但是,如果我想使用更高级别的切片,它将无法正常工作并返回NaN:
# not working
df.loc[:,idx['three',:]] - df.loc[:,idx['two',:]]
是否有一种简单的方法可以使用df的更高级别的切片并仅添加/减去相应的列?我的数据框可能在multiindex中包含数百列。谢谢
答案 0 :(得分:4)
如果需要输出中的MultiIndex,请将rename
用于相同级别的MultiIndex:
df = df.loc[:,idx['three',:]] - df.loc[:,idx['two',:]].rename(columns={'two':'three'})
print (df)
first three
second foo bar
A -0.861579 3.157731
B -1.944822 0.772031
C 2.649912 2.621137
可以将两个级别重命名为新的索引名称并加入原始索引:
df = (df.join(df.loc[:,idx['three',:]].rename(columns={'three':'four'}) -
df.loc[:,idx['two',:]].rename(columns={'two':'four'})))
print (df)
first one two three four \
second foo bar foo bar foo bar foo
A -1.085631 0.997345 0.282978 -1.506295 -0.578600 1.651437 -0.861579
B -2.426679 -0.428913 1.265936 -0.866740 -0.678886 -0.094709 -1.944822
C 1.491390 -0.638902 -0.443982 -0.434351 2.205930 2.186786 2.649912
first
second bar
A 3.157731
B 0.772031
C 2.621137
如有必要,请使用DataFrame.xs
:
df1 = df.xs('three', axis=1, level=0) - df.xs('two', axis=1, level=0)
print (df1)
second foo bar
A -0.861579 3.157731
B -1.944822 0.772031
C 2.649912 2.621137
如果需要第一级的解决方法是MultiIndex.from_product
:
df1 = df.xs('three', axis=1, level=0) - df.xs('two', axis=1, level=0)
df1.columns = pd.MultiIndex.from_product([['new'], df1.columns],
names=['first','second'])
print (df1)
first new
second foo bar
A -0.861579 3.157731
B -1.944822 0.772031
C 2.649912 2.621137
答案 1 :(得分:1)
您可以尝试DataFrame.xs
(横截面):
df.xs(('three'), axis=1) - df.xs(('two'), axis=1)
答案 2 :(得分:1)
在这种情况下,最简单的方法可能是:
df.loc[:, 'two'] - df.loc[:, 'three']
您几乎需要了解有关MultiIndex的所有信息,都可以在@coldspeed的canonicals
中