LoginSignup
0
0

More than 3 years have passed since last update.

Python の nan チェック

Last updated at Posted at 2021-01-07

TL;DR

a is np.nan じゃなくて np.isnan(a) を使おう。

nan

nan (Not A Number) です。nan「数値」じゃなくて、その比較についてはIEEE754で定義されています。これは何と比較しても等しくならない。nan == nan すらFalse です。Python の場合、math.nannp.nan があります。(他にもあるかも知れないけれど。)

一部で流通している誤解: 「a is np.nan でチェックできるよ」

anan の場合、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() があるんだから、それ使えば簡潔・正確・誤用防止といいことづくめなのに…。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0