Pandas:根据列中的条件测试替换记录

Pandas: replace records based on conditional test in column

我在数据框中有唯一的记录,没有重复记录,由跨多个列的值组合确定:

import pandas as pd
d = {'Alpha' : ['C', 'B', 'C','D', 'A', 'A'], 'Beta' : ['G', 'F', 'G', 'H', 'A', 'A'],'Year': ['Base', 88, 94, 22, 'Base', 66], 'Zulu' : [1, 2, -3, 4, 5, -3]}
df = pd.DataFrame(d)   

这让我们:

  Alpha Beta  Year  Zulu
0     C    G  Base     1
1     B    F    88     2
2     C    G    94    -3
3     D    H    22     4
4     A    A  Base     5
5     A    A    66    -4

索引 0 与索引 2 接近匹配,索引 4 与索引 5 接近匹配,除了索引 0 和索引 4 的 'Year' 值为 Base,并且 'Zulu'索引 2 和 5 的值为负。我想用索引 0 和 4 中相应的 Zulu 值替换 2 和 5 中的负 'Zulu' 值,而不破坏其他行。输出 df 将如下所示:

  Alpha Beta  Year  Zulu
0     C    G  Base     1
1     B    F    88     2
2     C    G    94     1
3     D    H    22     4
4     A    A  Base     5
5     A    A    66     5

我可以轻松地从过滤器和深度复制开始以避免切片问题,然后备份原始数据:

df_sub = df[df.Zulu < 0].copy(deep=True)
df_sub['Zulu_backup'] = df_sub.Zulu

然后我可以使用df_sub与原来的合并:

df_result = pd.merge(df_sub, df, how='right')

导致:

Alpha Beta  Year    Zulu     Zulu_backup
0     C    G    94    -3         -3.0
1     A    A    66    -3         -3.0
2     C    G  Base     1          NaN
3     B    F    88     2          NaN
4     D    H    22     4          NaN
5     A    A  Base     5          NaN

但我不知道从这里到哪里才能不弄乱数据框的其他行。我有一个相当复杂的脚本。我猜我可以创建一个系列并将其映射到数据框,但我不知道该怎么做。迭代这不是一个选项,因为我有数百万行。非常感谢任何帮助。

一种方法是将 Zulu 中的负值转换为 nan,然后 fillna

df.loc[df['Zulu'] < 0, 'Zulu'] = np.nan
df['Zulu'] = df.groupby(['Alpha', 'Beta']).Zulu.apply(lambda x: x.ffill().bfill()).astype(int)


    Alpha   Beta    Year    Zulu
0   C       G       Base    1
1   B       F       88      2
2   C       G       94      1
3   D       H       22      4
4   A       A       Base    5
5   A       A       66      5

编辑:

df.Zulu=df.Zulu.mask(df.Zulu.lt(0))

df.Zulu=df.set_index(['Alpha','Beta']).Zulu.fillna(df.set_index(['Alpha','Beta']).dropna().Zulu).values
df
Out[89]: 
  Alpha Beta  Year  Zulu
0     C    G  Base   1.0
1     B    F    88   2.0
2     C    G    94   1.0
3     D    H    22   4.0
4     A    A  Base   5.0
5     A    A    66   5.0