【pandas】欠損値 (NaN) の処理

当サイトではアフィリエイトプログラムを利用して商品を紹介しています。

 

【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

 

コメント

  1. HNaito より:

    下記は誤植と思われますので、ご確認ください。
    NA_03 In[4] プログラムのコメントで、# 行に沿って → # 列に沿って

  2. あとりえこばと より:

    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: どういたしまして!もし何かわからないことがあったら、いつでも聞いてね。お互いにデータ処理のスキルを高めていきましょう!