与 NaN 相等的元素比较

Posted

技术标签:

【中文标题】与 NaN 相等的元素比较【英文标题】:Element-wise comparison with NaNs as equal 【发布时间】:2019-02-05 18:52:17 【问题描述】:

如果我运行以下代码:

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。

我认为这是基本功能,我一定是在问一个重复的问题,但我花了很多时间在 SO 或 Google 中搜索,但找不到。

【问题讨论】:

【参考方案1】:

想不出一个已经为你做这个的函数(奇怪)所以你可以自己做:

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

       a
0   True
1  False
2   True

注意括号的存在。在 pandas 中使用重载的按位运算符时需要注意优先级。

另一个选择是使用np.nan_to_num,如果你确定两个DataFrame的索引和列是相同的,那么这个结果是有效的:

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

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

np.nan_to_num 用一些填充值填充 NaN(数字为 0,字符串数组为 'nan')。

【讨论】:

谢谢。我更喜欢第一个选项。如果没有更好的结果,我会在几天后选择你的答案。 我猜这将等同于 Nonenp.nan 我还要假设这些总是浮动的,所以不会有任何None【参考方案2】:

np.iscloseequal_nan=True 一起使用:

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

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

atolrtol 都设置为零很重要,以避免在相似值上出现相等断言。

【讨论】:

酷!我隐约记得有一个带有equal_nan 参数的函数,但我并没有想到。 如果在这里将公差设置为 0 会怎样? 不过,您可能必须将 tols 设置为 0,对吗? .. 啊,被打败了【参考方案3】:

因为 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

【讨论】:

有趣的是,您可能还可以转换为字符串并重复。 ++ 谢谢文。我见过我的同事这样做,但有时它可能很危险,因为这个系列中可能已经存在这个神奇的词('NaN')。 或许可以改成dft1.astype(str).eq(dft2.astype(str))【参考方案4】:

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

【讨论】:

以上是关于与 NaN 相等的元素比较的主要内容,如果未能解决你的问题,请参考以下文章

与 NaN 不同,为啥浮点无穷大是相等的?

在 Javascript 中比较 NaN 值是不是相等

具有 NaN 相等性比较的 Pandas DataFrames

js中相等与不等

js ==与===区别(两个等号与三个等号)

与 Double.NaN 相等