2009-05-26 13 views
48

入力に少なくとも1つの非数値の値が含まれているかどうかを検出する関数を記述する必要があります。数値以外の値が見つかった場合は、エラーが発生します(計算では数値のみが返されるため)。入力配列の次元数は事前に分かっていません。関数はndimに関係なく正しい値を与える必要があります。余分な複雑さとして、入力は単一のfloatまたはnumpy.float64、またはゼロ次元配列のような奇妙なものでもあります。NumPy配列に少なくとも1つの数値以外の値が含まれているかどうかを検出しますか?

これを解決する明白な方法は、iterable以外のものが見つかるまで、配列内のすべての反復可能オブジェクトを反復する反復関数を書くことです。すべての反復不能オブジェクトに対してnumpy.isnan()関数を適用します。少なくとも1つの数値以外の値が見つかった場合、関数は直ちに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 
+3

contains_nan' 'のためのあなたの説明が疑わしい:「少なくとも1つの非数値が存在する場合はfalseを返します」。配列にNaNが含まれている場合、 'contains_nan'が' True'を返すと思います。 –

+0

'array([None '、' None ']、dtype = object)'などの入力はどうでしょうか?そのような入力は単に例外を発生させるべきでしょうか? –

+0

'x 'に' float(' nan ')を使用しないでください。それは動作しません。 –

答えて

78

これは反復するよりも高速である必要があり、形状によらずに動作します:

は、ここに私のモックアップです。

numpy.isnan(myarray).any() 

編集:速く30X:

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 
+0

とnumpy 1.7 flatten()のバージョンは最初のものの2倍です –

+0

なぜ 'float( 'nan')in x'のようなものが動かないのですか?私はそれを試して、Pythonは 'x = [1,2,3、float( 'nan')]'のところで 'False'を返します。 –

+1

@CharlieParker float( 'nan')== float( 'nan')と同じ理由はFalseを返します。 NaNはNaNと等しくありません。ここでさらに情報:http://stackoverflow.com/questions/10034149/why-is-nan-not-equal-to-nan – Muppet

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の処理は、以前のバージョンでは一貫していませんでした。

+0

なぜ 'float( 'nan')in x'のようなものが動かないのですか?私はそれを試して、Pythonは 'x = [1,2,3、float( 'nan')]'のところで 'False'を返します。 –

+0

@CharlieParker ... NANとの比較は、あなたが期待することをしないためです。 NANは論理的なNULL(=わからない)のように扱われます。 'float(" nan ")== float(" nan ")' 'False'を返す(おそらくNANかNoneを返すはずです)。同様に、NANとboolen NULLの奇妙さは、SQLを含む多くの言語で真です(NULL = NULLは決して真ではありません)。 – user48956

9

無限が可能な値である場合、Trueに上記評価された場合、私はnumpy.isfinite

numpy.isfinite(myarray).all() 

を使用し、次いでmyarrayには、numpy.nannumpy.inf又は-numpy.inf値を含んでいません。 Ananの少なくとも一つの元素を含む場合、An x m行列かもしれ0よりも大きくなる

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) 
+0

なぜ 'float( 'nan')in x'のようなものが動かないのですか?私はそれを試して、Pythonは 'x = [1,2,3、float( 'nan')]'のところで 'False'を返します。 –

+1

@CharlieParker 2つの 'nan'sはお互いに等しいと見なされないためです。 'float( 'nan')== float( 'nan')'を試してください。 – Akavall

+0

興味深い。なぜ彼らは等しいと見なされないのですか? –

2

(np.where(np.isnan(A)))[0].shape[0]

numpy.nanは例えばnumpy.inf値とOKであろう。

例:

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" 
関連する問題