【pandas】欠損値の処理
一般に、pandas ではデータの欠損値 (NA : Not Available) に NaN (Not a Number) とよばれる特殊な浮動小数点数を割り当てます。たとえば、互いに異なるラベルをもつ Series 同士で演算を実行すると NaN が現れます。
# PANDAS_NAN # In[1] import numpy as np import pandas as pd # Seriseオブジェクトを作成 a = pd.Series([10, 20, 30], index=list("ABC")) b = pd.Series([ 5, 10, 15], index=list("BCD")) # aをbで除算 print(a / b) # A NaN # B 4.0 # C 3.0 # D NaN # dtype: float64
NaN は numpy.nan とよばれる 64bit浮動小数点数です。Python の欠損値オブジェクト None を含むリストから Series を生成した場合も、None は numpy.nan に変換されます。
# In[2] # Seriseオブジェクトを作成 d = pd.Series([None, 0, 1], index=list("ABC")) print(d) # A NaN # B 0.0 # C 1.0 # dtype: float64
dropna() で欠損値を削除する
以下のコードを実行すると、このサイトから CSV形式のテストデータ (10人の年齢、身長、体重のデータ) を読み込んで、DataFrame に変換します。このテストデータはいくつかの空白データがあるので、pandas で読み込んだときには、空白部分に NaN が割り当てられます。
# PANDAS_DROPNA # In[1] import numpy as np import pandas as pd # テストデータのURL u = "https://python.atelierkobato.com/wp-content/uploads/2019/07/pandas_test_04.csv" # テストデータを読み込んでDataFrameを作成 df = pd.read_csv(u, index_col=0) print(df) # age height weight # Allan 27 184.18 77.11 # Jeff 15 NaN 58.74 # Conrad 40 160.50 70.04 # Rowland 35 162.70 NaN # William 14 164.98 56.72 # Thomas 27 NaN NaN # Stewart 19 174.01 82.58 # Roy 31 167.49 77.04 # Brendan 23 NaN 61.18 # Scott 10 142.37 35.56
DataFrame の dropna()メソッド は欠損値 (NA) の存在する行をすべて取り除きます。
# In[2] # 欠損値を含む行をすべて削除 df_2 = df.dropna() print(df_2)
欠損値を含む列をすべて消去したい場合は dropna() に axis=1 または axis=”columns” を渡します。
# In[3] # 欠損値を含む列をすべて削除 df_3 = df.dropna(axis=1) print(df_3) # age # Allan 27 # Jeff 15 # Conrad 40 # Rowland 35 # William 14 # Thomas 27 # Stewart 19 # Roy 31 # Brendan 23 # Scott 10
次のデータ操作を解説するために、df の “Scott” の行をすべて NAN に置き換えておきます。
# In[4] # Scottの行をすべて NAN に置き換える df.loc["Scott"] = np.nan print(df) # age height weight # Allan 27.0 184.18 77.11 # Jeff 15.0 NaN 58.74 # Conrad 40.0 160.50 70.04 # Rowland 35.0 162.70 NaN # William 14.0 164.98 56.72 # Thomas 27.0 NaN NaN # Stewart 19.0 174.01 82.58 # Roy 31.0 167.49 77.04 # Brendan 23.0 NaN 61.18 # Scott NaN NaN NaN
dropna() はデフォルトで how=”any” が設定されていて、対象とする行や列に1つでも欠損値が含まれていると除去するようになっています。how=”all” に設定すると、すべての要素が欠損値となっている行や列のみを取り除きます。
# In[5] # すべての要素が欠損値となっている行を除去 df_4 = df.dropna(how="all") print(df_4) # age height weight # Allan 27.0 184.18 77.11 # Jeff 15.0 NaN 58.74 # Conrad 40.0 160.50 70.04 # Rowland 35.0 162.70 NaN # William 14.0 164.98 56.72 # Thomas 27.0 NaN NaN # Stewart 19.0 174.01 82.58 # Roy 31.0 167.49 77.04 # Brendan 23.0 NaN 61.18
引数 thresh は欠損値以外の要素の最小個数を指定します。
たとえば、df.drpopna(thresh=2) を実行すると、欠損値以外の要素が 2 個未満である Thomas と Scott の行を取り除きます。
# In[6] # 欠損値以外の要素が2個未満の行を削除 df_5 = df.dropna(thresh=2) print(df_5) # age height weight # Allan 27.0 184.18 77.11 # Jeff 15.0 NaN 58.74 # Conrad 40.0 160.50 70.04 # Rowland 35.0 162.70 NaN # William 14.0 164.98 56.72 # Stewart 19.0 174.01 82.58 # Roy 31.0 167.49 77.04 # Brendan 23.0 NaN 61.18
fillna() による欠損値の埋め込み処理
状況によっては、欠損値を削除せずに特定の数値や文字列を割り当てたほうがよいこともあるでしょう。fillna()メソッドは、Series と DataFrame に対して欠損値の埋め込み処理を実行します。fillna() の使用例を解説するために、最初に DataFrame を作成しておきます。
# PANDAS_FILLNA # In[1] import numpy as np import pandas as pd # 2次元配列を生成 arr = np.array([[1, np.nan, 2, 3], [np.nan, 4, np.nan, 5], [6, 7, np.nan, 8]]) # DataFrameを生成 df = pd.DataFrame(arr, columns=list("abcd")) print(df) # a b c d # 0 1.0 NaN 2.0 3.0 # 1 NaN 4.0 NaN 5.0 # 2 6.0 7.0 NaN 8.0
fillna() を使って、すべての欠損値に同じ値を割り当てることができます。
# In[2] # すべての欠損値に0を割り当てる df_10 = df.fillna(0) print(df_10) # a b c d # 0 1.0 0.0 2.0 3.0 # 1 0.0 4.0 0.0 5.0 # 2 6.0 7.0 0.0 8.0
method=”ffill” を渡すと、行または列に沿って1つ先の値を欠損値に割り当てます。
# In[3] # 行に沿って1つ先の値を割り当てる df_11 = df.fillna(method="ffill", axis=1) print(df_11) # a b c d # 0 1.0 1.0 2.0 3.0 # 1 NaN 4.0 4.0 5.0 # 2 6.0 7.0 7.0 8.0
method=”bfill” を渡すと、行または列に沿って1つ後ろの値を欠損値に割り当てます。
# In[4] # 列に沿って1つ後ろの値を割り当てる df_12 = df.fillna(method="bfill", axis=0) print(df_12) # a b c d # 0 1.0 4.0 2.0 3.0 # 1 6.0 4.0 NaN 5.0 # 2 6.0 7.0 NaN 8.0
isnull(), notnull() 欠損値の検出
欠損値を含む DataFrame を生成します。
# PANDAS_ISNULL # In[1] import numpy as np import pandas as pd # 2次元配列を生成 arr = np.array([[1, np.nan], [None, "a"]]) # DataFrameを生成 df = pd.DataFrame(arr, columns=list("AB")) print(df) # A B # 0 1 NaN # 1 None a
isnull()メソッドは欠損値を True, それ以外の値を False とするブール配列を返します。
# In[2] # 欠損値をTrueとするブール値配列を生成 b1 = df.isnull() print(b1) # A B # 0 False True # 1 True False
notnull()メソッドは欠損値を False, それ以外の値を True とするブール配列を返します。
# In[3] # 欠損値をFalseとするブール値配列を生成 b2 = df.notnull() print(b2) # A B # 0 True False # 1 False True
コメント
下記は誤植と思われますので、ご確認ください。
NA_03 In[4] プログラムのコメントで、# 行に沿って → # 列に沿って
直しておきました。
ありがとうございます。m(_ _)m
NaNの処理についてIT社員が話し合います
A: こんにちは!最近、pandasを使ってデータ処理をしているんだけど、NaNって言葉をよく見かけるんだけど、具体的には何のことを指しているのか知ってる?
B: こんにちは!そうだね、NaNは”非数値(Not a Number)”の略称だよ。pandasでは、データの欠損値や無効な値を表すために使われているんだ。
A: ああ、なるほど。つまり、データセット内の一部の値が欠けている場合や、計算が不可能な場合にNaNが使われるってこと?
B: そうだね、例えば、ある列の中に一部の行に対応する値が欠けている場合、その欠損値をNaNで表現することがあります。また、数値の計算中に無効な結果が出た場合にもNaNが使われるよ。
A: なるほど、データ処理中に欠損値があると、NaNを使うことでデータの整合性を保ちながら処理ができるんだね。
B: そうそう、NaNを適切に扱うことで、データ分析や機械学習のモデルの訓練など、データの品質を高めることができるんだ。pandasでは、NaNを検出したり、欠損値を処理したりするための便利なメソッドも提供されているよ。
A: なるほど、NaNはデータ処理でよく使われる要素なんだね。次回データの処理をするときには、NaNについても意識してみようと思うよ。ありがとう!
B: どういたしまして!もし何かわからないことがあったら、いつでも聞いてね。お互いにデータ処理のスキルを高めていきましょう!