为啥在 numpy `nan == nan` 中是 False 而 [nan] 中的 nan 是 True?

Posted

技术标签:

【中文标题】为啥在 numpy `nan == nan` 中是 False 而 [nan] 中的 nan 是 True?【英文标题】:Why in numpy `nan == nan` is False while nan in [nan] is True?为什么在 numpy `nan == nan` 中是 False 而 [nan] 中的 nan 是 True? 【发布时间】:2013-12-17 16:08:40 【问题描述】:

虽然问题的第一部分(在标题中)之前已经回答过几次(即Why is NaN not equal to NaN?),但我不明白为什么第二部分会这样工作(受此启发问题How to Check list containing NaN)?

即:

>> nan == nan
False

>> nan in [nan]
True

考虑到@DSM 的答案的问题的解释性附录。那么,为什么float("nan") 的行为与nan 不同?它不应该再次评估为简单的nan,为什么解释器会这样?

>> x = float("nan")
>> y = nan
>> x
nan
>> y
nan
>> x is nan, x is float("nan"), y is nan
(False, False, True)

基本上,它在第一种情况下引用相同的通用nan,但在第二种情况下创建单独的对象:

>> nans = [nan for i in range(2)]
>> map(id, nans)
[190459300, 190459300]
>> nans = [float("nan") for i in range(2)]
>> map(id, nans)
[190459300, 190459301]

【问题讨论】:

补充说明,float('nan') 总是创建一个新对象。您正在测试的 nan 是一个预先存在的对象,它永远不会与新创建的对象具有相同的 ID。 Python 中的赋值总是简单地引用原始对象;无论b 是什么,a = b; a is b 将始终返回 True 【参考方案1】:

nan 不等于 nannan 定义的一部分,所以这部分很简单。

至于nan in [nan] 为真,那是因为在列表中包含相等性之前测试了身份。您正在比较相同的两个对象。

如果你用两个不同 nans 尝试同样的事情,你会得到 False:

>>> nans = [float("nan") for i in range(2)]
>>> map(id, nans)
[190459300, 190459284]
>>> nans
[nan, nan]
>>> nans[0] is nans[1]
False
>>> nans[0] in nans
True
>>> nans[0] in nans[1:]
False

您的附录与nan 没有太大关系,这就是 Python 的工作原理。一旦您了解 float("nan") 没有义务返回一些 nan 单例,并且 y = x 不会复制 x 而是将名称 y 绑定到由 x 命名的对象,就有什么都没有了。

【讨论】:

嗯...为什么第一个例子中的nan是一样的?为什么不将它们初始化为两个不同的对象?因为x = nannan in [x] 仍然返回True @sashkello:你指的第一个例子是什么?你的nan == nannan 命名一个特定对象(在这种情况下,我很确定它是 np.nan)。不管你说多少次这个名字,它仍然指向同一个对象:没有初始化。类似地,x = nan 不会复制nan,它只是将x 命名为一个新名称,并说它命名了同样由nan 命名的对象。例如,在这样做之后尝试x is nan 我只是看不出这与 float("nan") 有什么不同呢? nan有不同的“味道”吗?否则,据我了解, float("nan") 仍应返回 nan ,它又是一个相同的对象,不是吗?我想了解为什么nan in [nan] 与 [float("nan")] 中的 `nan 不同?解释器如何知道列表中的 nan 是通过不同的方式获得的?我也不明白为什么 [float("nan")] 中的 float("nan") 在这种情况下是错误的...... 不,正如我在原始问题中所说,nans 不是唯一的对象。看上面的文字记录:两个nans有不同的id,nans[0] is nans[1]是False。 nan in [nan] 是 True,因为它基本上是 any(x is nan or x == nan for x in [nan])x is nan 是 True,所以 x == nan 是 False 并不重要。应用于nan in [float("nan")] 的相同规则给出x is nan 为假(它们是不同的对象)并且x == nan 仍然为假。 float("nan") in [float("nan")] 给出 False 因为他们是两个独立的 NANS。 @sashkello,这并不重要,但实际上有 种不同风格的 NaN,也有信号 NaN,它们的行为相同。

以上是关于为啥在 numpy `nan == nan` 中是 False 而 [nan] 中的 nan 是 True?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 itertools.groupby 可以将 NaN 分组在列表中而不是 numpy 数组中

Pandas/Numpy NaN 无比较

在没有numpy的python中分配一个变量NaN

在 numpy 数组求和中将 nan 视为零,但所有数组中的 nan 除外

为啥我的输出总是以 NaN 的形式出现,我期待输出作为我的系列数据?

从 pandas 转换为 numpy 后,如果数组包含 nan,则删除“nan”或减少 numpy 数组的长度 [重复]