静かなる名辞

pythonとプログラミングのこと


numpyでnanを含む配列の同値性をちゃんと計算する

はじめに

 2つのnumpy配列が同一であるかどうか調べたいシチュエーションは、ままあるでしょう。

 で、こうする訳です。

>>> import numpy as np
>>> a = np.array([1,2,3])
>>> b = np.array([1,2,3])
>>> (a == b).all()
True

 すべての要素同士を比較して、論理積を取ればすべて等しいかどうかわかる。素晴らしいですね。

 これでよかったら世の中平和なんですが、そうは問屋が卸さない。nanという厄介な存在があります。

nan同士の同値性比較はFalseになる - 静かなる名辞

>>> a = np.array([0.5, np.nan, 1])
>>> b = np.array([0.5, np.nan, 1])
>>> (a == b).all()
False

 悲しいですね。これをTrueにしたいと思っても、気軽になんとかできる手段はありません。

 なんとかしたいところです*1

片っ端から試す

 勇ましいタイトルつけたけど、リファレンスみたら使えそうなのが2つしかなかったです。

Logic functions — NumPy v1.17 Manual

numpy.array_equal

 たまに見るやつ。

>>> np.array_equal(a, b)
False

 撃沈。なんとかしてくれそうなオプションもなし。

numpy.allclose

 こっちは使えます。 

numpy.allclose(a, b, rtol=1e-05, atol=1e-08, equal_nan=False)
numpy.allclose — NumPy v1.17 Manual

 equal_nanという素敵な引数があります。

 でもやりたいことはcloseじゃなくてequalなんですけど……と思ったので、rtolとatol(詳しく知りませんが「近さ」の上限値的な役割を果たすはずです。詳細はリファレンスをちゃんと読んでください)を0に設定して使います。

>>> np.allclose(a, b, 0, 0, True)
True

 できた。位置引数として渡しているのでオマジナイ感がすごい。

まとめ

 nanってほんと面倒くさいですねぇ。

*1:だじゃれ