每级减去同列多指标

Subtract same column multi index for each level

这个问题看起来很基础,但我找不到任何答案。

我有一个多索引数据框,看起来像这样

           A                 B      
     a     b     c     a     b     c 
   x y z x y z x y z x y z x y z x y z
 1 : : :
 2 : :
 3 :
 4
 5
 6
 7

我只想创建另一个显示 x-z 和 y-z 的数据框。 我试图减去切片器,但它给了我 NaN(尽管尺寸相同)

 test.loc[:,idx[:,:,'x']].sub(test.loc[:,idx[:,:,'z']])

你知道完成这个任务的诀窍吗?

Pandas 操作(例如减法)总是根据行和列索引对齐 NDFrame。由于 df.loc[:,idx[:,:,'x']]df.loc[:,idx[:,:,'z']] 具有不同的列索引,因此减法会产生 NaN:

x = df.loc[:,idx[:,:,'x']]
z = df.loc[:,idx[:,:,'z']]
x.sub(z)

#     A                       B                    
#     a       b       c       a       b       c    
#     x   z   x   z   x   z   x   z   x   z   x   z
# 0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
# 1 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
# 2 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
# 3 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
# 4 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
# 5 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
# 6 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

要使 Pandas 按元素执行操作(忽略索引),请通过使 z 成为 NumPy 数组来删除索引:

x = df.loc[:,idx[:,:,'x']]
z = df.loc[:,idx[:,:,'z']].values
x.sub(z)
   A        B      
   a  b  c  a  b  c
   x  x  x  x  x  x
0  1 -1 -1 -1 -5 -1
1  0  1  0  4 -2  1
2 -5 -9  4  7 -5 -2
3 -5 -2 -6 -6  0  0
4 -3 -4  4 -5 -6  8
5  1  4 -7  7 -4  8
6  4  0 -2  1  3 -6

例如,

import pandas as pd
import numpy as np
np.random.seed(2016)
columns = pd.MultiIndex.from_product([['A', 'B'], ['a', 'b', 'c'], ['x', 'y', 'z']])
df = pd.DataFrame(np.random.randint(10, size=(7, 18)), columns=columns)

idx = pd.IndexSlice
x = df.loc[:,idx[:,:,'x']]
y = df.loc[:,idx[:,:,'y']]
z = df.loc[:,idx[:,:,'z']].values
result = pd.concat([x-z, y-z], axis=1)
result = result.rename(columns={'x':'x-z', 'y':'y-z'})

产量

    A           B           A           B        
    a   b   c   a   b   c   a   b   c   a   b   c
  x-z x-z x-z x-z x-z x-z y-z y-z y-z y-z y-z y-z
0   1  -1  -1  -1  -5  -1   5   4  -2   3  -8   0
1   0   1   0   4  -2   1   1   5   1   4   6   0
2  -5  -9   4   7  -5  -2  -9  -5   4   8   4   4
3  -5  -2  -6  -6   0   0  -5  -7   0  -4   3  -2
4  -3  -4   4  -5  -6   8  -2  -1   2  -8   1   1
5   1   4  -7   7  -4   8   0   2  -8   3   2   5
6   4   0  -2   1   3  -6   2   5   5   6  -2  -2