pandas
のDataFrame
, Series
では、.dropna()
メソッドを使うと簡単に欠損値NaN
を含む行・列を削除できます。
しかし、実際に欠損値除去する際には次のような疑問を抱くことも…。
- 行を除去するか、列を除去するか指定したい!
- 行の要素が全部
NaN
のとき、or 一つでもあるときに行・列を除去するには? - 特定の列に
NaN
があるときだけ、行を削除する方法はある?
この記事では、これらの疑問を解決するために.dropna()
メソッドについて、図解・サンプルコード付きで詳しく解説します。
.dropnaの基本
DataFrame
, Seriesで
、NaN
の行や列を削除するには、.dropna()
メソッドを使用します。
デフォルト設定で.dropna()
を実行すると、一つでNaN
がある行を削除したDataFrame
, Series
を返します。
次のサンプルコードで、基本挙動を確認してみましょう。
import pandas as pd
data = [[1, 2, 3],
[4, None, None],
[7, 8, None],
[10, 11, 12]]
df = pd.DataFrame(data,
index=["Row1", "Row2", "Row3", "Row4"],
columns=["Col1", "Col2", "Col3"])
# Col1 Col2 Col3
# Row1 1 2.0 3.0
# Row2 4 NaN NaN # ←欠損値がある行①
# Row3 7 8.0 NaN # ←欠損値がある行②
# Row4 10 11.0 12.0
デフォルト設定で".dropna()"
メソッドを実行してみます。
df.dropna()
# Col1 Col2 Col3
# Row1 1 2.0 3.0
# Row4 10 11.0 12.0
期待通りに、欠損値が一つでもある行が削除されましたね。
以下では、.dropnan()
の引数を指定して、欠損値の除去方法を指定する方法をわかりやすく解説していきます。
- 【参考】
[リスト]
からのDataFrame
生成方法については、次の記事で詳しく解説していきます。
.dropna()の追加設定一覧
上述の通り、デフォルト設定ではNaN
を一つでも含む行が削除されます。
.dropna()
メソッドでは、引数で除去方法の詳細設定を変更できます。
設定変更用の引数一覧を次の表にまとめています。
設定内容 | 引数 | 適用例 |
---|---|---|
行の除去 or 列の除去を指定 |
axis=0 or 1 または"index" or"columns" |
0 or "index" →行を除去(デフォルト)1 or "columns" →列を除去 |
一つでもNaN or全て NaN で除去の指定 |
how="any" or "all" |
"any" →一つでもNaN なら除去(デフォルト)"all" →全てNaN だと除去 |
NaN 調査行・列の指定 |
subset="ラベル名" または ["ラベル名"リスト] |
指定列or行のみがNaN 調査対象に |
行・列を残すための 有効値数の指定 |
thresh=数値 |
thresh 以上の有効値で行or列が残る |
DataFrame 上書き指定 |
inplace=False or True |
False →新規DataFrame を生成(デフォルト)True →もとのDataFrame を更新 |
引数と設定内容の関係を図にまとめると次のようになります。
以下では、各設定について詳しく解説していきます。
- 【参考】抽出、除去、補間といった欠損値NaN処理方法一覧については、次の記事にまとめたいます。
行or列の除去を指定
デフォルトでは、一つでもNaN
を含む行が除去されました。
行ではなく、列を除去するようする場合は、引数axis
を指定します。
- 行の除去 →
axis=0 or "index"
(デフォルト) - 列の除去 →
axis=1 or "columns"
axis=0, 1
を指定して、行・列を除去した際の挙動をそれぞれ確認してみましょう。
# サンプルデータフレーム
df
# Col1 Col2 Col3
# Row1 1 2.0 3.0
# Row2 4 NaN NaN
# Row3 7 8.0 NaN
# Row4 10 11.0 12.0
# 行の除去(デフォルト設定)
df.dropna() # df.dropna(axis=0) or df.dropna(axis="index")でも同様
# Col1 Col2 Col3
# Row1 1 2.0 3.0
# Row4 10 11.0 12.0
# 列の除去
df.dropna(axis=1) # df.dropna(axis="columns")でも同様
# Col1
# Row1 1
# Row2 4
# Row3 7
# Row4 10
一つでもNaN or 全てNaNで除去
デフォルトでは、NaN
が一つでも含まれている行が削除されます。
引数how
を指定すると、列or行の要素が一つでもNaNだと除去するのか、全てNaN
だと除去するのか指定できます。
- 一つでも
NaN
で除去 →how="all"
(デフォルト) - 全て
NaN
で除去 →how="any"
全てNaN
の行をもつdf2
を準備して、挙動を確認してみましょう。
df2 = df.copy()
df2.loc["Row2", "Col1"] = None
# Col1 Col2 Col3
# Row1 1.0 2.0 3.0
# Row2 NaN NaN NaN
# Row3 7.0 8.0 NaN
# Row4 10.0 11.0 12.0
how="any", "all"
の挙動を確認してみましょう
# サンプルデータフレーム
df
# Col1 Col2 Col3
# Row1 1 2.0 3.0
# Row2 4 NaN NaN
# Row3 7 8.0 NaN
# Row4 10 11.0 12.0
# how="any"(デフォルト):一つでもあると除去
df2.dropna(how="any")
# Col1 Col2 Col3
# Row1 1.0 2.0 3.0
# Row4 10.0 11.0 12.0
# how="all":全てNaNだと除去
df2.dropna(how="all")
# Col1 Col2 Col3
# Row1 1.0 2.0 3.0
# Row3 7.0 8.0 NaN
# Row4 10.0 11.0 12.0
how="any"
では、NaN
が含まれている"Row2", "Row3"
が除去されています。
一方、how="all"
では、全てNaN
である"Row2
だけが除去されていますね。
NaNを調べる行・列の指定
デフォルト設定では、全ての列を対象にNaN
があるかを調査します。
NaN
を調査する行を指定したい場合は、引数subset
で設定できます。
subset="ラベル名" or ["ラベル名"リスト等]
[リスト等]
はArray_like
ならOK
subset
で、調査する列を指定した場合の挙動を確認してみましょう。
# サンプルデータフレーム
# Col1 Col2 Col3
# Row1 1 2.0 3.0
# Row2 4 NaN NaN
# Row3 7 8.0 NaN
# Row4 10 11.0 12.0
# デフォルト:全ての列がNaN調査対象
df.dropna()
# Col1 Col2 Col3
# Row1 1 2.0 3.0
# Row4 10 11.0 12.0
# subset=["Col1", "Col2"]で、"Col1", "Col2"内のNaNを調査
df.dropna(subset=["Col1", "Col2"])
# Col1 Col2 Col3
# Row1 1 2.0 3.0
# Row3 7 8.0 NaN
# Row4 10 11.0 12.0
subset=["Col1", "Col2"]
を指定すると、"Col3"
のNaN
は調査対象外です。
たしかに、Col3
にNaN
があっても、行が除去されていませんね。
- 【参考】インデックス、カラムの設定方法については、次の記事で詳しく解説していきます。
行・列を残すための有効値数指定
thresh
を指定すると、行or列を保持するために必な有効値の数を指定できます。
thresh=有効値数(NaN以外のデータの個数)
NaN
の有無ではなく、列or行内の有効値が不足する場合に行・列を除去するための引数です。
欠損値ではなく、有効値を基準にした考え方という点に注意しましょう。
# サンプルデータフレーム
df
# Col1 Col2 Col3
# Row1 1 2.0 3.0
# Row2 4 NaN NaN
# Row3 7 8.0 NaN
# Row4 10 11.0 12.0
# thresh=2、有効値が2個以上の行のみ保持
df.dropna(thresh=2)
# Col1 Col2 Col3
# Row1 1 2.0 3.0
# Row3 7 8.0 NaN
# Row4 10 11.0 12.0
# thresh=3で、有効値が3個以上の行のみ保持
df.dropna(thresh=3)
# Col1 Col2 Col3
# Row1 1 2.0 3.0
# Row4 10 11.0 12.0
thresh=2
では、有効値が1つしかない"Row2"
が除去されました。
thresh=3
では、さらに有効値が2つしかない"Row3"
も除去されましたね。
DataFrame上書き指定
デフォルト設定では、.dropna()
はNaN
を除去した新たなDataFrame
を生成します。
引数inplaceで、新たにDataFrame
を生成するか、もとのDataFrame
を更新するか指定できます。
False
→ 新規DataFrame
を生成(デフォルト)True
→ もとのDataFrame
を更新
サンプルデータで挙動を確認してみましょう。
# デフォルト:新たにDataFrameを生成。※もとのdfは変更されない。
df_res = df.dropna()
print(df)
# もとのDataFrame, dfは変更なし
# Col1 Col2 Col3
# Row1 1 2.0 3.0
# Row2 4 NaN NaN
# Row3 7 8.0 NaN
# Row4 10 11.0 12.0
# df_resにNaNを除去した新規DataFrameを格納
print(df_res)
# Col1 Col2 Col3
# Row1 1 2.0 3.0
# Row4 10 11.0 12.0
# inplace=True:もとのDataFrame自身を更新
df.dropna(inplace=True)
# もとのDataFrame, dfのNaN行を削除
print(df)
# Col1 Col2 Col3
# Row1 1 2.0 3.0
# Row4 10 11.0 12.0
inplace
は、他の多くのメソッドと共通の引数ですね。
オススメ|pandasとデータ分析の勉強方法
今回はDataFrameから欠損値を除去する.dropna()
メソッドについて解説しました。
pandas
は便利すぎて操作方法がわかりにくいことがよくあります…。
結局はコツコツ学ぶのが、pandas
マスターの近道ですよね!
データ分析初心者の方にはこちらの記事もおススメです。
私がこれまで勉強してきた経験をもとに考えたおススメの勉強本の紹介記事です。
何から始めて、どうやってレベルアップしていけばいいのか、初心者の方にぜひおススメしたい本を紹介しました。
オススメのpandas
本については、次の記事で紹介しています。