根据 Pandas DF 中的条件生成 NA

Make NA based on condition in Pandas DF

我觉得这可能有一个简单的解决方案,我就是想不通。

我有一个 Pandas DF 类似于这个 MWE:

In [92]: test_df = pd.DataFrame({'A': [1,2,3,4,5,6,7,8,9], 'B':[9,8,7,6,5,4,3,2,1]})

In [93]: test_df
Out[93]: 
   A  B
0  1  9
1  2  8
2  3  7
3  4  6
4  5  5
5  6  4
6  7  3
7  8  2
8  9  1

我想要的是将那个 df 中所有小于 4 的值设置为 np.nan。我可以根据这个条件得到布尔值的 df:

In [94]: test_df < 4
Out[94]: 
       A      B
0   True  False
1   True  False
2   True  False
3  False  False
4  False  False
5  False  False
6  False   True
7  False   True
8  False   True

但我不知道生成这些 True 值的最后一步 np.nan。我认为这可以通过 test_df.loc 实现,但我的尝试没有成功。

您可以使用 boolean indexing:

分配 NaN
In [25]: test_df[test_df < 4] = np.nan

In [26]: test_df
Out[26]:
     A    B
0  NaN  9.0
1  NaN  8.0
2  NaN  7.0
3  4.0  6.0
4  5.0  5.0
5  6.0  4.0
6  7.0  NaN
7  8.0  NaN
8  9.0  NaN

具有 "negated" 条件的替代解决方案:

In [43]: test_df.where(test_df >= 4)
Out[43]:
     A    B
0  NaN  9.0
1  NaN  8.0
2  NaN  7.0
3  4.0  6.0
4  5.0  5.0
5  6.0  4.0
6  7.0  NaN
7  8.0  NaN
8  9.0  NaN

或:

In [47]: test_df.where(~(test_df < 4))
Out[47]:
     A    B
0  NaN  9.0
1  NaN  8.0
2  NaN  7.0
3  4.0  6.0
4  5.0  5.0
5  6.0  4.0
6  7.0  NaN
7  8.0  NaN
8  9.0  NaN

使用DataFrame.mask,默认情况下boolean maskTrue值被NaN替换:

print (test_df.mask(test_df < 4))
     A    B
0  NaN  9.0
1  NaN  8.0
2  NaN  7.0
3  4.0  6.0
4  5.0  5.0
5  6.0  4.0
6  7.0  NaN
7  8.0  NaN
8  9.0  NaN

另一个解决方案是反转条件和简单赋值:

test_df = test_df[test_df >= 4]
print (test_df)
     A    B
0  NaN  9.0
1  NaN  8.0
2  NaN  7.0
3  4.0  6.0
4  5.0  5.0
5  6.0  4.0
6  7.0  NaN
7  8.0  NaN
8  9.0  NaN