pandas DataFrame根据不同的列设置布尔掩码的值

时间:2018-05-03 15:37:08

标签: python pandas numpy dataframe

假设我们想要根据A_1B_1中的掩码替换B_2和'A_2'中的值。例如,将A(至999)中与B中的空值对应的值替换。

原始数据框:

   A_1  A_2  B_1  B_2
0    1    4    y    n
1    2    5    n  NaN
2    3    6  NaN  NaN

所需的数据框

   A_1  A_2  B_1  B_2
0    1    4    y    n
1    2  999    n  NaN
2  999  999  NaN  NaN

代码:

df = pd.DataFrame({
     'A_1': [1, 2, 3], 
     'A_2': [4, 5, 6], 
     'B_1': ['y', 'n', np.nan], 
     'B_2': ['n', np.nan, np.nan]})

_mask = df[['B_1', 'B_2']].notnull()
df[['A_1', 'A_2']] = df[['A_1','A_2']].where(_mask, other=999)

但我得到以下内容:

   A_1  A_2  B_1  B_2
0  999  999    y    n
1  999  999    n  NaN
2  999  999  NaN  NaN

所以,所有的都被替换了,而不仅仅是not null。我该如何解决这个>

我关注的是this answer,但 只有在我使用相同的列 时才有效:

df[['B_1', 'B_2']] = odf[['B_1','B_2']].where(_mask, other=999)

   A_1  A_2  B_1  B_2
0    1    4    y    n
1    2    5    n  999
2    3    6  999  999

3 个答案:

答案 0 :(得分:1)

存在索引问题(在列名称上)。将掩码转换为numpy数组,你可以去:

df[['A_1', 'A_2']] = df.filter(like='A').mask(
    df.filter(like='B').isnull().values, 999
)

df
   A_1  A_2  B_1  B_2
0    1    4    y    n
1    2  999    n  NaN
2  999  999  NaN  NaN

或者,将它保存在numpy空间中:

df[['A_1', 'A_2']] = np.where(
    df.filter(like='B').isnull(), 999, df.filter(like='A')
)

df
   A_1  A_2  B_1  B_2
0    1    4    y    n
1    2  999    n  NaN
2  999  999  NaN  NaN

答案 1 :(得分:1)

您的代码适用于np.where

df[['A_1', 'A_2']] = np.where(_mask, df[['A_1', 'A_2']], 999)
>>> df
A_1 A_2 B_1 B_2
0   1   4   y   n
1   2   999 n   NaN
2   999 999 NaN NaN

因为它是一个numpy级别的函数,在任何情况下都不知道列名。

答案 2 :(得分:0)

所以问题是_mask中列的名称被称为不同。一个选项是重命名列,因此它们与目标相同:

_mask = df[['B_1', 'B_2']].notnull()
_mask.columns = ['A_1', 'A_2']
df[['A_1', 'A_2']] = df[['A_1','A_2']].where(_mask, other=999)

或者,如果您只是调用values属性

,则更容易
_mask = df[['B_1', 'B_2']].notnull().values
df[['A_1', 'A_2']] = df[['A_1','A_2']].where(_mask, other=999)