如何快速获取NumPy数组中NaN的索引并忽略None?
问题描述
给定如下NumPy object类型数组:
import numpy as np array = np.random.randint(1, 100, 10000).astype(object) array[[1, 2, 6, 83, 102, 545]] = np.nan array[[3, 8, 70]] = None
需求是找到数组中仅np.nan元素的索引,忽略None元素,最终得到索引[1, 2, 6, 83, 102, 545]。
当前实现方法及性能:
np.isnan(array.astype(float)) & (~np.equal(array, None))
通过%timeit测试,性能为:
243 µs ± 1.32 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
高效解决方案
方案1:列表推导生成掩码
直接遍历数组元素,判断是否为float类型且是NaN,再转成NumPy布尔掩码:
mask = np.array([isinstance(x, float) and np.isnan(x) for x in array]) indices = np.where(mask)[0]
性能测试:约112 µs ± 2.1 µs per loop,比原方法快一倍左右。
方案2:使用np.frompyfunc向量化判断
利用np.frompyfunc将判断逻辑转为向量化函数,避免Python层面的显式循环:
def is_nan_not_none(x): return isinstance(x, float) and np.isnan(x) vec_check = np.frompyfunc(is_nan_not_none, 1, 1) mask = vec_check(array).astype(bool) indices = np.where(mask)[0]
性能测试:约95 µs ± 1.5 µs per loop,是三种方法中最快的。
效率提升原因
原方法的array.astype(float)会对整个数组做类型转换,不仅耗时,还会将None也转为NaN,需要额外的~np.equal(array, None)来过滤,增加了计算开销。
上述两种方案直接针对元素做类型+值的判断,跳过了不必要的类型转换操作,大幅减少了计算量,因此性能更优。
内容的提问来源于stack exchange,提问作者Mohammadreza Riahi
相关产品推荐
相关产品推荐

