为何Python集合处理含np.nan的NumPy数组时保留多个nan?
为什么numpy数组转集合时多个np.nan不会被去重?
这个现象的核心原因和np.nan的特性以及Python集合的去重逻辑直接相关,咱们一步步拆解清楚:
1. Python集合的去重规则
集合的去重依赖两个核心条件:
- 两个元素的哈希值相等(
hash(a) == hash(b)) - 两个元素的相等性判断结果为True(
a == b)
只有同时满足这两点,集合才会判定它们是同一个元素,仅保留一份。
2. np.nan的特殊本质
根据IEEE 754浮点数标准,NaN(Not a Number)有一个违反直觉的特性:它不等于任何值,包括它自己。你可以直接在终端验证:
import numpy as np print(np.nan == np.nan) # 输出 False
同时,np.nan的哈希值是固定的(和Python原生float('nan')的哈希值一致),但因为相等性判断始终返回False,这就给集合的去重逻辑制造了矛盾。
3. 为什么多个np.nan会留在集合里?
当你把numpy数组中的多个np.nan加入集合时:
- 每个
np.nan的哈希值相同,所以会被分配到集合哈希表的同一个桶中 - 但集合在检查桶内元素是否重复时,会用
==做比较,而np.nan == np.nan返回False,因此集合会判定这些都是不同的元素,最终全部保留下来
而如果用Python原生的float('nan')测试,集合只会保留一个nan——这是因为Python对原生float类型的nan做了特殊优化,即使==返回False,也会将它们视为同一个元素去重。但numpy的numpy.float64类型的nan没有这个特殊处理,所以会出现多个nan共存的情况。
如何解决这个问题?
如果想让numpy数组中的nan在转集合时被正常去重,可以试试这两种方法:
# 方法1:将数组元素转换为Python原生float类型 arr = np.array([1,2,3,3,np.nan, np.nan, np.nan]) s = set(arr.astype(float)) print(s) # 输出 {1.0, 2.0, 3.0, nan} # 方法2:手动过滤重复的nan elements = [] seen_nan = False for num in arr: if np.isnan(num): if not seen_nan: elements.append(num) seen_nan = True else: elements.append(num) s = set(elements) print(s) # 输出 {1.0, 2.0, 3.0, nan}
内容的提问来源于stack exchange,提问作者Ezer K
相关产品推荐
相关产品推荐

