【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