Pandas 多索引根据其他列中的值从值中减去

Pandas multi-index subtract from value based on value in other column

给定以下数据框:

df = pd.DataFrame({
    ('A', 'a'): [23, 'n/a',54,7,32,76],
    ('B', 'b'): [23, 'n/a',54,7,32,76],
    ('possible','possible'):[100,100,100,100,100,100]
    })
df
    A       B   possible
    a       b   
0   23      23      100
1   n/a     n/a     100
2   54      54      100
3   7       n/a     100
4   32      32      100
5   76      76      100

我想针对 'n/a' 的每个实例每行调整 'possible',这样每个实例将从 'possible' 中减去 4。 想要的结果如下:

    A       B   possible
    a       b   possible
0   23      23      100
1   n/a     n/a     92
2   54      54      100
3   7       n/a     96
4   32      32      100
5   76      76      100

然后完成后,我希望将 'n/a' 的每个实例都转换为 0,以便列类型为整数(但 float 可以)。

提前致谢!

后续问题:

如果我的多索引是这样的怎么办:

df = pd.DataFrame({
        ('A', 'a'): [23, 'n/a',54,7,32,76],
        ('A', 'b'): [23, 'n/a',54,7,32,76],
        ('B', 'b'): [23, 'n/a',54,7,32,76],
        ('possible','possible'):[100,100,100,100,100,100]
        })

我有 5 个上层索引和 25 个下层索引。我想知道是否可以只引用

中的顶部
no4 = (df.loc[:, (top level indices),(bottom level indices)] == 'n/a').sum(axis=1) 

我认为您可以通过掩码检查值 boolean indexing. Last replace 所有值 n/a0:

使用 n/asum 检查值:

idx = pd.IndexSlice
no4 = (df.loc[:, idx[('A', 'B'), ('a', 'b')]] == 'n/a').sum(axis=1) 
print no4
0    0
1    2
2    0
3    1
4    0
5    0
dtype: int64

检查总和是否相等 0(这意味着有 n/a 个值):

mask = no4 != 0
print mask
0    False
1     True
2    False
3     True
4    False
5    False
dtype: bool

减去 4no4:

df.loc[mask, idx['possible', 'possible']] -= no4 * 4
df.replace({'n/a':0}, inplace=True)
print df
    A   B possible
    a   b possible
0  23  23    100.0
1   0   0     92.0
2  54  54    100.0
3   7   0     96.0
4  32  32    100.0
5  76  76    100.0

编辑:

我找到了更简单的解决方案 - 掩码不是必需的,因为如果 n/a:

你减去 0
idx = pd.IndexSlice
print (df.loc[:, idx[('A', 'B'), ('a', 'b')]] == 'n/a').sum(axis=1) * 4
0    0
1    8
2    0
3    4
4    0
5    0
dtype: int64

df.loc[:, idx['possible', 'possible']] -= 
(df.loc[:, idx[('A', 'B'), ('a', 'b')]] == 'n/a').sum(axis=1) * 4
df.replace({'n/a':0}, inplace=True)
print df
    A   B possible
    a   b possible
0  23  23      100
1   0   0       92
2  54  54      100
3   7   0       96
4  32  32      100
5  76  76      100

EDIT1:如果您只需要 select tom indices - 请参阅 using slicers:

(df.loc[:, idx[(top level indices),:]] == 'n/a').sum(axis=1)