TL;DR
a is np.nan
じゃなくて np.isnan(a)
を使おう。
nan
nan (Not A Number) です。nan「数値」じゃなくて、その比較についてはIEEE754で定義されています。これは何と比較しても等しくならない。nan == nan
すらFalse
です。Python の場合、math.nan
と np.nan
があります。(他にもあるかも知れないけれど。)
一部で流通している誤解: 「a is np.nan
でチェックできるよ」
a
が nan
の場合、a == np.nan
ではチェックできません。なぜならば上述のとおり、IEEE754でそう決められているから。で、どうするかと言うと、いくつかのサイトでは a is np.nan
とすればいいよ、とあります。確かに多くの場合これでうまく行くのですが、これはどうやらnumpyやmathの実装上、たまたまうまく行く(同一のnanオブジェクトを参照するようになっている)ことが多い だけのようで、基本的に間違ったチェック方法と断じたいと思います。
というわけで反例。
# 以下は Python 3.91 + numpy 1.19.4 で試しました。math の nan でも基本的に同じです。
import numpy as np
a = np.nan
b = a * 2
print(a) # => nan
print(b) # => nan
print(a is np.nan) # => True (これがよく使われる。これはok)
print(b is np.nan) # => False (こういうことが起こる。)
nan
に対して演算をしてしまうことはありますよね? その結果はやはり(当然?) nan
です。ここで is
で比較をしてしまうと、参照先が異なるようで Flase
になってしまいます。だから a is np.nan
は(nan かどうかのチェックとしては)誤り。
正解は?
素直に np.isnan()
を使うのが良いでしょう。わかりやすいし。定義を逆手に取った裏技(?)として自身との比較 a == a
(が False
だったら nan
) というのもあるのですが、混乱するのでぼくは遠慮しときます。
悪者は誰か? (個人の感想です。あまりツッコまないでください。)
Python です(バッサリ)。is
なんてモノを導入したのが諸悪の根源だと。こういう「直観的な機能が曖昧なbe動詞」に「参照先の比較」という大切な働きをさせるから混乱が生じる。さらに悪いことに、is
の式は読みようによっては(意味を勘違いしたままでも)英文的にわかりやすいので広まっちゃう。is
なんかなくたって、id()
があるんだから、それ使えば簡潔・正確・誤用防止といいことづくめなのに…。