将NaN视为相等进行逐元素比较

15

如果我运行以下代码:

dft1 = pd.DataFrame({'a':[1, np.nan, np.nan]})
dft2 = pd.DataFrame({'a':[1, 1, np.nan]})
dft1.a==dft2.a

结果是

0     True
1    False
2    False
Name: a, dtype: bool

我该如何使结果变为

0     True
1    False
2     True
Name: a, dtype: bool
即,np.nan == np.nan 的结果是True。 我认为这是基本功能,我可能是在问重复的问题,但我花了很多时间在Stack Overflow或Google上搜索,却找不到答案。
4个回答

13

想不出已经为您完成此操作的函数(奇怪),因此您可以自己编写:

dft1.eq(dft2) | (dft1.isna() & dft2.isna())

       a
0   True
1  False
2   True

请注意括号的存在。在使用pandas中重载的按位运算符时,优先级是需要注意的一个问题。

另一个选择是使用np.nan_to_num,如果您确定两个数据框的索引和列是相同的,则可以使用此结果:

np.nan_to_num(dft1) == np.nan_to_num(dft2)

array([[ True],
       [False],
       [ True]])

np.nan_to_num用某个填充值(数值型为0,字符串数组为'nan')替换NaN值。


谢谢。我更喜欢第一个选项。如果没有更好的方案出现,我会在几天内选择您的答案。 - GoCurry
我猜这将等同于 Nonenp.nan - piRSquared
我还要假设这些始终是浮点数,因此不会有任何“None”。 - piRSquared

8

使用 np.isclose 时,设置 equal_nan=True

np.isclose(dft1, dft2, equal_nan=True, rtol=0, atol=0)

array([[ True],
   [False],
   [ True]])

atolrtol同时设置为零非常重要,以避免在相似值上进行等式断言。


很酷!我模糊地记得有一个带有equal_nan参数的函数,但我不能立刻想起来。 - cs95
1
如果您在这里将公差设置为0会怎样? - cs95
1
你可能需要将 tols 设置为 0,对吧?啊,被打败了。 - DSM

4

由于np.nan不等于np.nan

np.nan==np.nan
Out[609]: False



dft1.a.fillna('NaN')==dft2.a.fillna('NaN')
Out[610]: 
0     True
1    False
2     True
Name: a, dtype: bool

1
有趣的是,你可能还可以将其转换为字符串并重复。++ - cs95
谢谢Wen。我看到我的同事们做过这样的事情,但有时候会很危险,因为魔术词(在你的案例中是'NaN')可能已经存在于序列中。 - GoCurry
1
也许可以尝试使用 dft1.astype(str).eq(dft2.astype(str)) - cs95

2

np.nan被定义为不等于np.nan

迭代

检查每对是否相等全部是np.nan

def naneq(t):
  return (t[0] == t[1]) or np.isnan(t).all()

[*map(naneq, zip(dft1.a, dft2.a))]

[True, False, True]

nunique

计算唯一值的数量。请确保设置参数dropna=False.

pd.concat([dft1, dft2], axis=1).nunique(1, 0) == 1

0     True
1    False
2     True
dtype: bool

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接