web-dev-qa-db-ja.com

numpyの「less_equalで無効な値が発生しました」の原因は何ですか

RuntimeWarningを経験しました

 RuntimeWarning: invalid value encountered in less_equal

私のこのコード行によって生成された:

center_dists[j] <= center_dists[i]

両方 center_dists[j]およびcenter_dists[i]はnumpy配列です

この警告の原因は何ですか?

24
Alex Gao

これは、関連する入力のどこかにnp.nanがあるために発生する可能性が最も高くなります。その例を以下に示します-

In [1]: A = np.array([4, 2, 1])

In [2]: B = np.array([2, 2, np.nan])

In [3]: A<=B
RuntimeWarning: invalid value encountered in less_equal
Out[3]: array([False,  True, False], dtype=bool)

np.nanを含むすべての比較について、Falseを出力します。 broadcasted 比較のために確認しましょう。これがサンプルです-

In [1]: A = np.array([4, 2, 1])

In [2]: B = np.array([2, 2, np.nan])

In [3]: A[:,None] <= B
RuntimeWarning: invalid value encountered in less_equal
Out[3]: 
array([[False, False, False],
       [ True,  True, False],
       [ True,  True, False]], dtype=bool)

出力の3番目の列は、Bの3番目の要素np.nanを含む比較に対応し、すべてのFalse値になります。

29
Divakar

Divakarの答えとRuntimeWarningを抑制する方法に関する彼のコメントのフォローアップとして、より安全な方法は、それらをlocallywith np.errstate()(- docs ):通常、_np.nan_との比較でFalseが生成された場合にアラートが発生し、これが本当に発生した場合にのみ警告を無視する意図するもの。 OPの例は次のとおりです。

_with np.errstate(invalid='ignore'):
  center_dists[j] <= center_dists[i]
_

withブロックを終了すると、エラー処理は以前の状態にリセットされます。

_invalid value encountered_の代わりに、_all='ignore'_を渡すことですべてのエラーを無視することもできます。興味深いことに、これはnp.errstate()のドキュメントのkwargsにはありませんが、 np.seterr() のドキュメントにはありません。 (np.errstate()ドキュメントの小さなバグのようです。)

5
Ulrich Stern

Numpy dtypeは非常に厳密です。したがって、np.array([False, True, np.nan])のような配列は生成されず、float配列であるarray([ 0., 1., nan])を返します。

次のようなブール配列を変更しようとした場合:

_x= np.array([False, False, False])
x[0] = 5
_

array([ True, False, False]) ...を再実行します

しかし、_5>np.nan_はFalseにはできません。nanである必要があり、Falseはデータ比較が行われ、_3>5_、これは災害だと思います。 Numpyは、実際には持っていないデータを生成します。 nanを返すことができた場合、簡単に処理できます。

そこで、関数を使用して動作を変更しようとしました。

_def ngrater(x, y):
    with np.errstate(invalid='ignore'):
        c=x>y
        c=c.astype(np.object)
        c[np.isnan(x)] = np.nan
        c[np.isnan(y)] = np.nan
        return c
a = np.array([np.nan,1,2,3,4,5, np.nan, np.nan, np.nan]) #9 elements
b = np.array([0,1,-2,-3,-4,-5, -5, -5, -5]) #9 elements

ngrater(a,b)
_

戻り値:array([nan, False, True, True, True, True, nan, nan, nan], dtype=object)

しかし、メモリ構造全体がそのように変更されると思います。統一された単位でメモリブロックを取得する代わりに、実際のデータがどこかにあるポインタのブロックを生成します。そのため、関数の実行速度が遅くなる可能性があり、それがNumpyがそうしない理由です。 _np.nan_も含むsuperBool dtypeが必要です。または、float配列_+1:True, -1:False, nan:nan_を使用する必要があります。

0

これは、データフレーム内のNan値が原因で発生しますが、DFではまったく問題ありません。

Pycharmでは、これは私にとって魅力的なものでした:

import warnings

warnings.simplefilter(action = "ignore", category = RuntimeWarning)
0
Revanth M