pandasで欠損値NaNを削除(除外)するdropna

Modified: | Tags: Python, pandas

pandas.DataFrame, Seriesの欠損値NaNを削除(除外)するにはdropna()メソッドを使う。

欠損値NaNの抽出・置換・カウントについては以下の記事を参照。

なお、pandasではNaN(Not a Number: 非数)のほか、Noneも欠損値として扱われる。

本記事のサンプルコードのpandasのバージョンは以下の通り。バージョンによって仕様が異なる可能性があるので注意。例として、空白を含むCSVファイルを読み込んで使用する。

import pandas as pd

print(pd.__version__)
# 2.0.3

df = pd.read_csv('data/src/sample_pandas_normal_nan.csv')
print(df)
#       name   age state  point  other
# 0    Alice  24.0    NY    NaN    NaN
# 1      NaN   NaN   NaN    NaN    NaN
# 2  Charlie   NaN    CA    NaN    NaN
# 3     Dave  68.0    TX   70.0    NaN
# 4    Ellen   NaN    CA   88.0    NaN
# 5    Frank  30.0   NaN    NaN    NaN

すべての値が欠損値NaNである行・列を削除: how='all'

dropna()の引数how'all'とすると、すべての値が欠損値の行が削除される。

print(df.dropna(how='all'))
#       name   age state  point  other
# 0    Alice  24.0    NY    NaN    NaN
# 2  Charlie   NaN    CA    NaN    NaN
# 3     Dave  68.0    TX   70.0    NaN
# 4    Ellen   NaN    CA   88.0    NaN
# 5    Frank  30.0   NaN    NaN    NaN

引数axis1または'columns'とすると、すべての値が欠損値の列が削除される。

print(df.dropna(how='all', axis=1))
#       name   age state  point
# 0    Alice  24.0    NY    NaN
# 1      NaN   NaN   NaN    NaN
# 2  Charlie   NaN    CA    NaN
# 3     Dave  68.0    TX   70.0
# 4    Ellen   NaN    CA   88.0
# 5    Frank  30.0   NaN    NaN

引数axis0または'index'とすると行が削除される。デフォルトがaxis=0なので、省略した場合は最初の例のように行が削除される。

以前はaxis=[0, 1]とすると行と列がどちらも削除されたが、バージョン1.0.0からリストやタプルでの指定はサポートされなくなった。行・列両方を削除したい場合はdropna()を繰り返し適用すればよい。

# print(df.dropna(how='all', axis=[0, 1]))
# TypeError: supplying multiple axes to axis is no longer supported.

print(df.dropna(how='all').dropna(how='all', axis=1))
#       name   age state  point
# 0    Alice  24.0    NY    NaN
# 2  Charlie   NaN    CA    NaN
# 3     Dave  68.0    TX   70.0
# 4    Ellen   NaN    CA   88.0
# 5    Frank  30.0   NaN    NaN

欠損値NaNが一つでも含まれる行・列を削除: how='any'(デフォルト)

すべての値が欠損値である行と列を削除したデータを例とする。

df2 = df.dropna(how='all').dropna(how='all', axis=1)
print(df2)
#       name   age state  point
# 0    Alice  24.0    NY    NaN
# 2  Charlie   NaN    CA    NaN
# 3     Dave  68.0    TX   70.0
# 4    Ellen   NaN    CA   88.0
# 5    Frank  30.0   NaN    NaN

dropna()の引数how'any'とすると、欠損値が一つでも含まれる行が削除される。デフォルトがhow='any'なので、何も指定しないとこの動作になる。

print(df2.dropna(how='any'))
#    name   age state  point
# 3  Dave  68.0    TX   70.0

print(df2.dropna())
#    name   age state  point
# 3  Dave  68.0    TX   70.0

引数axis1または'columns'とすると、列に適用。欠損値が一つでも含まれる列が削除される。

print(df2.dropna(axis=1))
#       name
# 0    Alice
# 2  Charlie
# 3     Dave
# 4    Ellen
# 5    Frank

欠損値NaNではない要素の数に応じて行・列を削除: thresh

dropna()の引数threshに個数を指定すると、欠損値ではない要素の数に応じて行・列を削除できる。

例えばthresh=3とすると、欠損値ではない要素の数が3個以上含まれている行が残り、それ以外の行(欠損値ではない要素の数が3個未満の行)が削除される。

print(df.dropna(thresh=3))
#     name   age state  point  other
# 0  Alice  24.0    NY    NaN    NaN
# 3   Dave  68.0    TX   70.0    NaN
# 4  Ellen   NaN    CA   88.0    NaN

引数axis1または'columns'とすると、列に適用。

print(df.dropna(thresh=3, axis=1))
#       name   age state
# 0    Alice  24.0    NY
# 1      NaN   NaN   NaN
# 2  Charlie   NaN    CA
# 3     Dave  68.0    TX
# 4    Ellen   NaN    CA
# 5    Frank  30.0   NaN

特定の行・列に欠損値NaNがある列・行を削除: subset

特定の行・列を基準に削除したい場合は、dropna()の引数subsetに対象としたい行名・列名(行ラベル・列ラベル)をリストで指定する。対象が一つでもsubset=['name']のようにリストで指定する必要がある。

デフォルトはhow='any', axis=0なので、subsetで指定した列に欠損値がある行が削除される。

print(df.dropna(subset=['age']))
#     name   age state  point  other
# 0  Alice  24.0    NY    NaN    NaN
# 3   Dave  68.0    TX   70.0    NaN
# 5  Frank  30.0   NaN    NaN    NaN

print(df.dropna(subset=['age', 'state']))
#     name   age state  point  other
# 0  Alice  24.0    NY    NaN    NaN
# 3   Dave  68.0    TX   70.0    NaN

引数how'all'とすると、指定した列すべてが欠損値である行が削除される。

print(df.dropna(subset=['age', 'state'], how='all'))
#       name   age state  point  other
# 0    Alice  24.0    NY    NaN    NaN
# 2  Charlie   NaN    CA    NaN    NaN
# 3     Dave  68.0    TX   70.0    NaN
# 4    Ellen   NaN    CA   88.0    NaN
# 5    Frank  30.0   NaN    NaN    NaN

引数axis1または'columns'とすると、subsetで指定した行に欠損値がある列が削除される。引数howも同時に指定可能。

print(df.dropna(subset=[0, 4], axis=1))
#       name state
# 0    Alice    NY
# 1      NaN   NaN
# 2  Charlie    CA
# 3     Dave    TX
# 4    Ellen    CA
# 5    Frank   NaN

print(df.dropna(subset=[0, 4], axis=1, how='all'))
#       name   age state  point
# 0    Alice  24.0    NY    NaN
# 1      NaN   NaN   NaN    NaN
# 2  Charlie   NaN    CA    NaN
# 3     Dave  68.0    TX   70.0
# 4    Ellen   NaN    CA   88.0
# 5    Frank  30.0   NaN    NaN

存在しない行名・列名を指定するとエラー。axis=1としたのに列名を指定した場合などもエラーになる。

# print(df.dropna(subset=['age', 'state', 'xxx']))
# KeyError: ['xxx']

# print(df.dropna(subset=['age', 'state'], axis=1))
# KeyError: ['age', 'state']

元のオブジェクトを変更: inplace

これまでの例のように、デフォルトでは新しいオブジェクトを返して元のオブジェクトは変更されないが、引数inplace=Trueとすると元のオブジェクト自体が変更される。

df.dropna(subset=['age'], inplace=True)
print(df)
#     name   age state  point  other
# 0  Alice  24.0    NY    NaN    NaN
# 3   Dave  68.0    TX   70.0    NaN
# 5  Frank  30.0   NaN    NaN    NaN

pandas.Seriesの場合

pandas.Seriesdropna()メソッドの有効な引数はinplaceのみ。一次元データなので単純に欠損値の要素が削除されるだけ。

s = pd.read_csv('data/src/sample_pandas_normal_nan.csv')['age']
print(s)
# 0    24.0
# 1     NaN
# 2     NaN
# 3    68.0
# 4     NaN
# 5    30.0
# Name: age, dtype: float64

print(s.dropna())
# 0    24.0
# 3    68.0
# 5    30.0
# Name: age, dtype: float64

s.dropna(inplace=True)
print(s)
# 0    24.0
# 3    68.0
# 5    30.0
# Name: age, dtype: float64

関連カテゴリー

関連記事