【PythonのNan判定の方法】 pandasはisnan

PythonのNaN判定

Pythonのif文でNaN判定する方法

Pythonのif文でfloat型の値をNaN判定

NaNを普段から「ナン」と私は呼んでますが、あってるんでしょうか?

調べたところ…NaNは読み方「ナン」で合ってます。本格カレーについてくるナンと同じ読み方!

※本場の読み方は「ネァン)」だそうですが、まあ日本国内ではナンで良さそうです。

NaNの読み方はナン

NaN(Not a number)は、一般的に、ありえない計算しようとした場合に発生します。例えば、0を0で除算、0に無限大を乗算、負数の対数や平方根などの場合です。ただ、Pythonの場合は、計算を行おうとした場合にエラーになってしまいます。

if文でNaNの判定をするのに便利な「math.isnan()」という関数が用意されています。試してみましょう。

#!/usr/bin/python3

import math

a=0
b=0
if( math.isnan(a/b) ) :
print( "NaN Error" )
exit()
c=a/b
print( c )

変数a,bにそれぞれ0を代入し、ゼロ除算の結果NaNになるようならNaN Errorと表示する、というスクリプト。しかし、結果はこうなります。

 File "./nan.py", line 7, in <module>
if( math.isnan(a/b) ) :
ZeroDivisionError: division by zero

エェェ!生エラー出た!

関連)pythonの0除算の回避方法

どうやら、isnanより先にa/bを計算したときにdivision by zeroエラーになってしまう模様。まあ、処理上はisnanを使わなくても、b=0かどうかをif文で判定すればいいんですけど…

どうやら、計算処理でNaNを生成すること自体が難しい模様。float(“nan”)で人為的にNaNを発生させることができるので、試してみました。

#!/usr/bin/python3

import math

c=float("nan")
if( math.isnan(c) ) :
print( "NaN Error" )
exit()
print( c )

実行するとこう。

c=NaNなので、print文でNaN Errorを表示しています。

関連 Pythonのprint

% ./nan.py
NaN Error

これだと、isnan()の存在意義がイマイチ感じられませんね。他のケースを調べてみましょう。

Pythonのリスト(list)のNaN判定

Pythonのリスト(list)のNaN判定

list中に含まれるNaNを判定するサンプルコード。

$ cat nanlist.py
#!/usr/bin/python3

import math

# list1 を作成
list1=[1,2,3,float('nan'),5,6,float('nan'),7]
print( list1 )

# isnan()=Falseのみ対象にlist1からlist2を作成
list2 = [x for x in list1 if math.isnan(x) == False]
print( list2 )

forとif文を組み合わせて、listからNaN判定がFalse(=NaNではない)値のみを抽出しています。forのこの書き方は「内包表記」という記述方法で、listの処理を高速化するための常套手段。

関連 Pythonのfor文

関連 Pythonのlist

上記のコードにnanlist.pyという名前をつけて保存し、実行するとこう。

$ ./nanlist.py
[1, 2, 3, nan, 5, 6, nan, 7]
[1, 2, 3, 5, 6, 7]

PythonのPandasデータフレーム(dataframe)のNaN判定

PythonのPandasデータフレーム(dataframe)のNaN判定

Pythonのライブラリ、Pandasで扱うデータフレームは、行と列で成り立つ表のようなデータ。二次元配列と考えれば良いかも知れません。

2次元配列に加えて、行番号とカラム名がセットになっています。

 name age
0 Taro 13.0
1 Hanako NaN
2 Jiro 12.0

以下は、データフレームの第二カラムがNaNではないものだけを抽出するサンプルコードです。リストの要素に対してforループでmath.isnan()を使ってNaN判定しています。

$ cat nandf.py
#!/usr/bin/python3
import pandas as pd
import math

# dataframesを作成
data = [['Taro',13],['Hanako',float('nan')],['Jiro',12]]

df = pd.DataFrame(data,columns =['name','age'])

print(df)

# ageがNaNでないものだけを表示
print( "### without NaN Value ###" )
for col_name, item in df.iterrows():
if( math.isnan(item[1]) == False ):
print( item[0], item[1] )

実行するとこうなります。

$ ./nandf.py
name age
0 Taro 13.0
1 Hanako NaN
2 Jiro 12.0
### without NaN Value ###
Taro 13.0
Jiro 12.0

データフレームの第二カラムageの値がNaNのものだけを除外してprint文で表示しています。

PythonのNumpyのNaN判定

PythonのNumpyのNaN判定

Numpyは高速で多次元配列の計算を行うためのライブラリ。

2×3の2次元配列に対して、第一要素、第二要素がともにNaNではないときに新規の2次元配列に追加するサンプルコードです。

$ cat ./nannumpy.py
#!/usr/bin/python3

import numpy as np
import math

# numpy arrayを生成
list=np.array([[1,2],[3,float('nan')],[5,6]])

# numpy array表示
print ( list )

# 配列の第一要素、第二要素がともにNaNではないときだけlist2に追加
list2 = [(x,y) for x,y in list if math.isnan(x) == False
and math.isnan(y) == False ]

# 新規に生成した numpy arrayを生成
print( list2 )

numpy行列の各要素にmath.isnan()でNaN判定。

np.array()で、numpy行列の初期化をおこなって、forの内包表記でnan判定を行いながらnumpy行列list2を作成、表示しています。

関連 Python 配列 値の初期化

実行するとこうなります。

$ ./nannumpy.py
[[ 1. 2.]
[ 3. nan]
[ 5. 6.]]
[(1.0, 2.0), (5.0, 6.0)]

PythonのNaN判定のまとめ

まとめ

  • PythonのNaNは、math.isnan()で判定が可能
  • Pythonで0除算などを行うと、NaNとはならずにDivision by zeroのエラーになる
  • listやデータフレームなどでNaN判定を行う場合は、forループ等で複数判定をおこなう