问题:检测NumPy数组是否包含至少一个非数值?
我需要编写一个函数来检测输入是否包含至少一个非数字值。如果找到一个非数字值,我将引发一个错误(因为该计算应仅返回一个数字值)。预先不知道输入数组的维数-无论ndim如何,函数都应给出正确的值。更为复杂的是,输入可能是单个浮点数,numpy.float64
或者甚至是零维数组之类的奇数。
解决此问题的明显方法是编写一个递归函数,该函数对数组中的每个可迭代对象进行迭代,直到找到一个非iterabe。它将numpy.isnan()
对每个不可迭代的对象应用该函数。如果找到至少一个非数字值,则该函数将立即返回False。否则,如果iterable中的所有值都是数字,它将最终返回True。
效果很好,但是速度很慢,我希望NumPy有更好的方法。什么是更快更麻木的替代品?
这是我的样机:
def contains_nan( myarray ):
"""
@param myarray : An n-dimensional array or a single float
@type myarray : numpy.ndarray, numpy.array, float
@returns: bool
Returns true if myarray is numeric or only contains numeric values.
Returns false if at least one non-numeric value exists
Not-A-Number is given by the numpy.isnan() function.
"""
return True
回答 0
这应该比迭代更快,并且无论形状如何都可以工作。
numpy.isnan(myarray).any()
编辑:快30倍:
import timeit
s = 'import numpy;a = numpy.arange(10000.).reshape((100,100));a[10,10]=numpy.nan'
ms = [
'numpy.isnan(a).any()',
'any(numpy.isnan(x) for x in a.flatten())']
for m in ms:
print " %.2f s" % timeit.Timer(m, s).timeit(1000), m
结果:
0.11 s numpy.isnan(a).any()
3.75 s any(numpy.isnan(x) for x in a.flatten())
奖励:它适用于非数组NumPy类型:
>>> a = numpy.float64(42.)
>>> numpy.isnan(a).any()
False
>>> a = numpy.float64(numpy.nan)
>>> numpy.isnan(a).any()
True
回答 1
如果无穷是一个可能的值,我将使用numpy.isfinite
numpy.isfinite(myarray).all()
如果以上计算结果为True
,则不myarray
包含numpy.nan
,numpy.inf
或-numpy.inf
值。
numpy.nan
可以使用numpy.inf
值,例如:
In [11]: import numpy as np
In [12]: b = np.array([[4, np.inf],[np.nan, -np.inf]])
In [13]: np.isnan(b)
Out[13]:
array([[False, False],
[ True, False]], dtype=bool)
In [14]: np.isfinite(b)
Out[14]:
array([[ True, False],
[False, False]], dtype=bool)
回答 2
ff!微秒!永远不要在几微秒内解决可以在十亿分之一秒内解决的问题。
注意接受的答案:
- 遍历整个数据,无论是否找到nan
- 创建一个大小为N的临时数组,该数组是多余的。
更好的解决方案是在找到NAN时立即返回True:
import numba
import numpy as np
NAN = float("nan")
@numba.njit(nogil=True)
def _any_nans(a):
for x in a:
if np.isnan(x): return True
return False
@numba.jit
def any_nans(a):
if not a.dtype.kind=='f': return False
return _any_nans(a.flat)
array1M = np.random.rand(1000000)
assert any_nans(array1M)==False
%timeit any_nans(array1M) # 573us
array1M[0] = NAN
assert any_nans(array1M)==True
%timeit any_nans(array1M) # 774ns (!nanoseconds)
并适用于n维:
array1M_nd = array1M.reshape((len(array1M)/2, 2))
assert any_nans(array1M_nd)==True
%timeit any_nans(array1M_nd) # 774ns
将此与numpy本机解决方案进行比较:
def any_nans(a):
if not a.dtype.kind=='f': return False
return np.isnan(a).any()
array1M = np.random.rand(1000000)
assert any_nans(array1M)==False
%timeit any_nans(array1M) # 456us
array1M[0] = NAN
assert any_nans(array1M)==True
%timeit any_nans(array1M) # 470us
%timeit np.isnan(array1M).any() # 532us
提前退出方法是3阶或幅度加速(在某些情况下)。对于简单的注解,不要太破旧。
回答 3
使用numpy 1.3或svn,您可以执行此操作
In [1]: a = arange(10000.).reshape(100,100)
In [3]: isnan(a.max())
Out[3]: False
In [4]: a[50,50] = nan
In [5]: isnan(a.max())
Out[5]: True
In [6]: timeit isnan(a.max())
10000 loops, best of 3: 66.3 µs per loop
比较中对Nans的处理在早期版本中不一致。
回答 4
(np.where(np.isnan(A)))[0].shape[0]
将大于0
如果A
含有的至少一种元素nan
,A
可以是一个n x m
矩阵。
例:
import numpy as np
A = np.array([1,2,4,np.nan])
if (np.where(np.isnan(A)))[0].shape[0]:
print "A contains nan"
else:
print "A does not contain nan"
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。