检测NumPy数组是否包含至少一个非数字值?

时间:2009-05-26 17:43:48

标签: python numpy

我需要编写一个函数来检测输入是否包含至少一个非数字值。如果找到非数字值,我将引发错误(因为计算应该只返回一个数值)。预先不知道输入数组的维数 - 无论ndim如何,该函数都应给出正确的值。作为一个额外的复杂功能,输入可以是单个浮点数或numpy.float64,甚至可以是像零维数组一样的奇怪数据。

解决这个问题的显而易见的方法是编写一个递归函数,该函数迭代数组中的每个可迭代对象,直到找到非迭代。它将numpy.isnan()函数应用于每个不可迭代的对象。如果找到至少一个非数字值,则该函数将立即返回False。否则,如果iterable中的所有值都是数字,则最终将返回True。

这很好用,但速度很慢,我希望NumPy有更好的方法。什么是更快,更numpyish的替代方案?

这是我的模型:

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

5 个答案:

答案 0 :(得分:133)

这应该比迭代更快,无论形状如何都能正常工作。

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 :(得分:13)

如果无穷大是一个可能的值,我会使用numpy.isfinite

    $ cp /home/uddi/root/hello `pwd`

and

$ cp /home/uddi/root/hello .

如果上述评估结果为numpy.isfinite(myarray).all() ,则True不包含任何,myarraynumpy.nannumpy.inf值。

-numpy.inf可以使用numpy.nan值,例如:

numpy.inf

答案 2 :(得分: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的处理在早期版本中并不一致。

答案 3 :(得分:2)

如果(np.where(np.isnan(A)))[0].shape[0]包含0的至少一个元素,则{p> A将大于nanA可能是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"

答案 4 :(得分:1)

Pfft!微秒! 永远不要在几微秒内解决可以在十亿分之一秒内解决的问题。

请注意,可接受的答案:

  • 对整个数据进行迭代,而不管是否找到nan
  • 创建一个大小为N的临时数组,这是多余的。

更好的解决方案是在找到NAN时立即返回True:

UPDATE `project.dataset.table` SET
  OL = ARRAY(SELECT AS STRUCT * REPLACE(1.1 * GROSS AS GROSS) FROM UNNEST(OL)),
  PL = ARRAY(SELECT AS STRUCT * REPLACE(1.2 * GROSS AS GROSS) FROM UNNEST(PL))

并适用于n维:

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)

将此与numpy本机解决方案进行比较:

array1M_nd = array1M.reshape((len(array1M)/2, 2))
assert any_nans(array1M_nd)==True
%timeit any_nans(array1M_nd)  # 774ns

早期退出方法是3阶或幅度加速(在某些情况下)。 对于简单的注解来说,并不是太破旧。