YutaKaのPython教室

Python の文法やライブラリ、API、環境構築について画像・動画・ソースコード付きで徹底解説!

図解で解決!pandasの欠損値NaNをdropnaで除去する方法

pandasDataFrame, 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生成方法については、次の記事で詳しく解説していきます。
≫pandas リストからDataFrameを生成|インデックスとコラムの設定も!
pandasでは、リストからデータフレームを生成することもできます。しかし、pandasの操作に慣れていないうちは、ちょっとした操作も難しいですよね。この記事では、①リストからデータフレームを生成、行と列を追加する方法、②インデックス名、コラム名を設定する方法、③DataFrameを転値する方法(行と列が期待と逆だった時の対応)をサンプルコード付きで紹介!
www.yutaka-note.com/entry/pandas_list
 

.dropna()の追加設定一覧

上述の通り、デフォルト設定ではNaNを一つでも含む行が削除されます。

.dropna()メソッドでは、引数で除去方法の詳細設定を変更できます。

設定変更用の引数一覧を次の表にまとめています。

設定内容 引数 適用例
行の除去 or
列の除去を指定
axis=0 or 1または
  "index" or"columns"
0 or "index"→行を除去(デフォルト)
1 or "columns"→列を除去
一つでもNaNor
全て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処理方法一覧については、次の記事にまとめたいます。
≫pandas 欠損値NaN処理一覧|抽出、除去、補間
pandasを使用すると欠損値NaNを効率的かつ高速に処理することができます。① NaNのある行や列を抽出する方法は?② NaNのある行や列を削除したい!③ NaNを他の値で置き換えたり、線形補間したりするにはどうするの?こんな悩みをサンプルコート付きでわかりやすく解決します!
www.yutaka-note.com/entry/pandas_na
 

行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は調査対象外です。

たしかに、Col3NaNがあっても、行が除去されていませんね。

  • 【参考】インデックス、カラムの設定方法については、次の記事で詳しく解説していきます。
≫pandas DataFrameにインデックス設定|パターン別にわかりやすく解説
pandasのDataFrameでは、インデックス名でデータにアクセスします。しかし、DataFrameへのインデックス指定方法は少しわかりにくい部分も…。そこで、この記事では、パターン別に設定方法を解説!①DataFrame作成時にインデックス列指定、②既存DataFrameで指定、③ExcelやCSVから読み込み時に指定 ④インデックスの振り直し…
www.yutaka-note.com/entry/pandas_index_setting
 

行・列を残すための有効値数指定

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】

データ分析初心者の方にはこちらの記事もおススメです。

私がこれまで勉強してきた経験をもとに考えたおススメの勉強本の紹介記事です。

何から始めて、どうやってレベルアップしていけばいいのか、初心者の方にぜひおススメしたい本を紹介しました。

≫独学でデータ分析を勉強するオススメ学習本
独学でのpythonデータ分析勉強に役立ったおススメ書籍を紹介していきます。業務でそれなりにデータ分析を行えるまで、いろいろな試行錯誤をしてきましたが、もし自分が今ゼロから勉強する立場ならどうするのがいいのか考えてみました。以下では、入門書、個別モジュール用、実践用の3つの視点でおススメ本を紹介していきます。
www.yutaka-note.com/entry/data_analysis
 

オススメのpandas本については、次の記事で紹介しています。

≫【レビュー】「Python実践データ分析100本ノック」|100本終えたらpandasが好きになっていた
Python実践データ分析100本ノックで、実際に100本終了したレビューです。pythonでのデータ分析の入門書としてかなりの良書だったと思います。・python2~3冊目に何を勉強しようか迷っている人・時間をかけずにデータ分析の基本を学びたい人・pandasへの抵抗を減らしたい人
www.yutaka-note.com/entry/nock_100
 
≫【レビュー】「Pythonによるデータ分析入門」| pandas開発者によるpandasユーザーのためのpandasの教科書!
「Pythonによるデータ分析入門」を、最初から最後まで実際に実践してみたレビューです。具体的にどのようなことができるようになったかを実例付きで紹介します!・DataFrameの生成方法・欠損値の処理方法・グラフ化の方法気になる学習時間は…?
www.yutaka-note.com/entry/2019/12/07/230219