私の単体テストでは、2つの配列が同一であるかどうかを確認したいと思います。縮小例:
a = np.array([1, 2, np.NaN])
b = np.array([1, 2, np.NaN])
if np.all(a==b):
print 'arrays are equal'
これは機能しませんnan != nan
。続行するための最良の方法は何ですか?
私の単体テストでは、2つの配列が同一であるかどうかを確認したいと思います。縮小例:
a = np.array([1, 2, np.NaN])
b = np.array([1, 2, np.NaN])
if np.all(a==b):
print 'arrays are equal'
これは機能しませんnan != nan
。続行するための最良の方法は何ですか?
1.19より前のバージョンのnumpyの場合、これは、単体テストを特に含まない状況でおそらく最良のアプローチです。
>>> ((a == b) | (numpy.isnan(a) & numpy.isnan(b))).all()
True
ただし、最新バージョンでは、array_equal
関数に新しいキーワード引数、が提供さequal_nan
れます。これは、法案に正確に適合します。
これはflyingdutchmanによって最初に指摘されました。詳細については、以下の彼の回答を参照してください。
numpy.testing.assert_equal
またはnumpy.testing.assert_array_equal
、try/except
:を使用することもできます。
In : import numpy as np
In : def nan_equal(a,b):
...: try:
...: np.testing.assert_equal(a,b)
...: except AssertionError:
...: return False
...: return True
In : a=np.array([1, 2, np.NaN])
In : b=np.array([1, 2, np.NaN])
In : nan_equal(a,b)
Out: True
In : a=np.array([1, 2, np.NaN])
In : b=np.array([3, 2, np.NaN])
In : nan_equal(a,b)
Out: False
編集
assert
これを単体テストに使用しているので、 (取得するためにラップするのではなく)ベアのTrue/False
方が自然かもしれません。
最も簡単な方法は、numpy.allclose()
メソッドを使用することです。これにより、nan値を持つ場合の動作を指定できます。次に、例は次のようになります。
a = np.array([1, 2, np.nan])
b = np.array([1, 2, np.nan])
if np.allclose(a, b, equal_nan=True):
print('arrays are equal')
その後arrays are equal
、印刷されます。
ここで関連ドキュメントを見つけることができます
numpyでマスクされた配列を使用し、NaN
値をマスクしてから、numpy.ma.all
またはnumpy.ma.allclose
:を使用できます。
http://docs.scipy.org/doc/numpy/reference/generated/numpy.ma.all.html
http://docs.scipy.org/doc/numpy/reference/generated/numpy.ma.allclose.html
例えば:
a=np.array([1, 2, np.NaN])
b=np.array([1, 2, np.NaN])
np.ma.all(np.ma.masked_invalid(a) == np.ma.masked_invalid(b)) #True
@Luis Albert Centenoの答えを完成させるために、次を使用することもできます。
np.allclose(a, b, rtol=0, atol=0, equal_nan=True)
rtol
atol
同等性テストの許容範囲を制御します。つまり、次のようになりallclose()
ます。
all(abs(a - b) <= atol + rtol * abs(b))
デフォルトでは0に設定されていないため、True
数値が近いが完全に等しくない場合、関数は戻る可能性があります。
PS:「2つの配列が同一であるかどうかを確認したい」>>実際、あなたは同一性ではなく平等を探しています。Pythonでは同じではないので、同じレキシコンを共有するためには、誰もが違いを理解する方が良いと思います。(https://www.blog.pythonlibrary.org/2017/02/28/python-101-equality-vs-identity/)
あなたはキーワードを介してアイデンティティをテストしますis
:
a is b
numpy関数array_equalは、質問の要件に完全に適合します。これが尋ねられたとき、それはおそらく存在していませんでした。例は次のようになります。
a = np.array([1, 2, np.NaN])
b = np.array([1, 2, np.NaN])
assert np.array_equal(a, b, equal_nan=True)
ただし、要素がdtypeの場合、これは機能しないという問題に注意してくださいobject
。これがバグかどうかわからない。
上記の答えを使用したとき:
((a == b) | (numpy.isnan(a) & numpy.isnan(b))).all()
文字列のリストを評価するときに、いくつかのエラーが発生しました。
これはより一般的なタイプです:
def EQUAL(a,b):
return ((a == b) | ((a != a) & (b != b)))
v1.9以降、numpyのarray_equal
関数はequal_nan
引数をサポートしています。
assert np.array_equal(a, b, equal_nan=True)
単体テストなどでこれを行う場合、すべてのタイプでパフォーマンスと「正しい」動作をあまり気にしない場合は、これを使用して、数値だけでなく、すべてのタイプの配列で機能するものを作成できます。
a = np.array(['a', 'b', None])
b = np.array(['a', 'b', None])
assert list(a) == list(b)
ndarray
sをlist
sにキャストすると、テストで必要な動作を取得するのに役立つ場合があります。(ただし、これを本番コードやより大きな配列では使用しないでください!)
私にとってこれはうまくいきました:
a = numpy.array(float('nan'), 1, 2)
b = numpy.array(2, float('nan'), 2)
numpy.equal(a, b, where =
numpy.logical_not(numpy.logical_or(
numpy.isnan(a),
numpy.isnan(b)
))
).all()
PS。nanがある場合は比較を無視します