1. ホーム
  2. python

[解決済み] NumPyの配列が少なくとも1つの非数値的な値を含んでいるかどうかを検出する?

2022-05-16 12:24:58

質問

入力に少なくとも1つの非数値が含まれているかどうかを検出する関数を書く必要があります。もし非数値が見つかったらエラーを出します(計算では数値しか返さないはずなので)。入力配列の次元数は事前に知ることができません。この関数は ndim に関係なく正しい値を返す必要があります。さらに複雑なこととして、入力は1つの浮動小数点または numpy.float64 あるいは0次元配列のような奇妙なものでさえも可能です。

これを解決する明らかな方法は、配列内のすべての反復可能なオブジェクトを反復し、反復不可能なオブジェクトを見つける再帰的な関数を書くことです。この関数は numpy.isnan() 関数を適用します。少なくとも1つの非数値が見つかった場合、この関数は直ちに False を返します。それ以外の場合は、反復可能なオブジェクトのすべての値が数値であれば、最終的に真を返します。

これは問題なく動作しますが、かなり遅いです。 NumPy はそれを行うためのより良い方法を持っています。より速く、より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

どのように解決するのですか?

これは反復処理より速く、形状に関係なく動作するはずです。

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