nan不能存入python标准set,因ieee 754规定nan≠nan,导致set依赖的哈希与相等性判断失效;应改用pandas的pd.unique()、dropna()后转set,或用isin().any()判断存在性。

NaN 不是普通值,不能用 == 或 in 判断,也不能直接放进 Python 的 set(因为 NaN != NaN),所以“集合中的 NaN”本质上是个伪命题——标准 set 无法容纳多个 NaN,甚至无法可靠判断它是否存在。真正需要处理的,通常是 list、Series 或 DataFrame 中混有 NaN 的情况,再考虑去重、过滤或统计等类似集合操作。
为什么 set 里放不了 NaN?
IEEE 754 规定 NaN 不等于自身:np.nan == np.nan 返回 False。而 Python 的 set 依赖哈希和相等性判断来去重,当两个 NaN 被插入 set 时,系统无法确认它们是否“相同”,实际行为是:第一个 NaN 可能被存入,后续 NaN 往往被忽略或导致不可预期结果。这不是 bug,而是浮点标准的固有特性。
替代方案:用 pandas 或 numpy 安全处理含 NaN 的“类集合”操作
若目标是去重、筛选或统计非空唯一值,推荐以下做法:
-
去重并保留非 NaN 值:先用
dropna()清洗,再转 set 或用unique()series_clean = series.dropna()<br>unique_values = set(series_clean)
-
保留 NaN 作为一类特殊标记:用
pd.unique()(它专为 pandas 设计,能正确识别 NaN 为一个独立元素)pd.unique([1, 2, np.nan, 2, np.nan])→array([1., 2., nan]) -
判断某值是否在含 NaN 的序列中:不要写
val in series,改用series.isin([val]).any()(自动兼容 NaN)或显式检查:(series == val).any() | (pd.isna(val) & series.isna().any())
对 list 做“类集合”清洗的实用写法
如果原始数据是 list,且含 NaN(如 [1, np.nan, 2, np.nan]),可这样安全提取唯一非空值:
- 过滤 NaN 后转 set:
set(x for x in my_list if not pd.isna(x)) - 用 numpy 掩码:
arr = np.array(my_list)<br>set(arr[~np.isnan(arr)])
(仅适用于全数值) - 保留原始类型(如含字符串和 NaN):
set(filter(lambda x: not pd.isna(x), my_list))
别踩坑:这些操作会出错
以下写法看似简洁,实则危险:
-
set(my_list)—— 若 list 含 NaN,结果不确定,可能丢值或报错 -
np.nan in my_list—— 永远返回False(因np.nan == np.nan为 False) -
my_list.count(np.nan)—— 返回 0,不可靠 - 用
dict.fromkeys(my_list)去重 —— NaN 键会被覆盖或失效











