pandasのdropna()の使い方|subset・how・thresh・axisで欠損値NaNの行・列を削除【pandas 3.0対応】
pandasのdropna()は、欠損値(NaN・None・pd.NAなど)を含む行や列を取り除くメソッドです。引数なしなら欠損が1つでもある行を削除し、特定の列だけを見るならsubset=["列名"]、全部欠けている行だけならhow="all"、「値が何個あれば残すか」ならthresh、列を消すならaxis=1を指定します。
この記事では、同じ表を使って各引数で何行残るのかを実際に動かして比べます。コードはPython 3.12・pandas 3.0.6で実行し、引数の説明は公式ドキュメント(pandas.DataFrame.dropna、pandas 3.0.6(2026年10月15日確認))に合わせています。
dropna()の引数一覧
| 引数 | 既定値 | 意味 |
|---|---|---|
axis |
0 |
0または"index"で行を、1または"columns"で列を削除する |
how |
"any" |
"any"は欠損が1つでもあれば削除、"all"は全部欠損のときだけ削除 |
thresh |
なし | 欠損でない値がこの個数以上ある行(列)だけ残す。howとは同時に指定できない |
subset |
なし | 欠損を調べる列(axis=1のときは行)を限定する |
inplace |
False |
Trueなら元のDataFrameを書き換え、戻り値はNone |
ignore_index |
False |
Trueなら結果の行番号を0から振り直す(pandas 2.0.0で追加) |
基本:欠損が1つでもある行を削除する
以下の5行の表を例にします。name・age・scoreのあちこちに欠損があります。
import numpy as np
import pandas as pd
df = pd.DataFrame({
"name": ["佐藤", "鈴木", "高橋", "田中", None],
"age": [25, np.nan, 31, np.nan, np.nan],
"score": [80, 72, np.nan, np.nan, np.nan],
})
print(df)
print()
print(df.dropna())
実行結果:
name age score
0 佐藤 25.0 80.0
1 鈴木 NaN 72.0
2 高橋 31.0 NaN
3 田中 NaN NaN
4 NaN NaN NaN
name age score
0 佐藤 25.0 80.0
引数なしのdropna()はhow="any"と同じで、どこか1つでも欠損がある行をすべて削除します。この表では、すべての値がそろっている0行目しか残りません。実際のデータでは、引数なしで実行すると思った以上に行が減ることがよくあります。まずdf.isna().sum()で列ごとの欠損数を確認してから、次のsubsetやthreshで条件を絞るのがおすすめです。
subset:特定の列に欠損がある行だけ削除する
「年齢が分からない行だけ除きたい」のように、判断に使う列を決めたいときはsubsetを使います。指定した列だけを見て、そこに欠損がある行を削除します。他の列に欠損があっても行は残ります。
import numpy as np
import pandas as pd
df = pd.DataFrame({
"name": ["佐藤", "鈴木", "高橋", "田中", None],
"age": [25, np.nan, 31, np.nan, np.nan],
"score": [80, 72, np.nan, np.nan, np.nan],
})
print(df.dropna(subset=["age"]))
print()
print(df.dropna(subset=["age", "score"], how="all"))
print()
print(df.dropna(subset="score"))
実行結果:
name age score
0 佐藤 25.0 80.0
2 高橋 31.0 NaN
name age score
0 佐藤 25.0 80.0
1 鈴木 NaN 72.0
2 高橋 31.0 NaN
name age score
0 佐藤 25.0 80.0
1 鈴木 NaN 72.0
結果を順に見ます。
subset=["age"]:ageが欠けている1・3・4行目が消え、scoreが欠けている2行目は残るsubset=["age", "score"], how="all":2列の両方が欠けている3・4行目だけが消えるsubset="score":列が1つなら、リストにせず文字列で渡しても動く
subsetに複数の列を渡したとき、howを省略すると"any"(どれか1つでも欠けていれば削除)になります。「どちらか一方でも値があれば残したい」なら、上の2つ目の例のようにhow="all"を組み合わせます。存在しない列名を渡すとKeyErrorになる点にも注意してください(後述)。
how=”all”:全部欠けている行だけ削除する
CSVの末尾に空行がある、Excelから読み込んだら空の行が混ざった、というときはhow="all"が便利です。すべての値が欠損している行だけを削除し、一部でも値がある行は残します。
import numpy as np
import pandas as pd
df = pd.DataFrame({
"name": ["佐藤", "鈴木", "高橋", "田中", None],
"age": [25, np.nan, 31, np.nan, np.nan],
"score": [80, 72, np.nan, np.nan, np.nan],
})
print(df.dropna(how="all"))
print()
print(df.dropna(thresh=2))
実行結果:
name age score
0 佐藤 25.0 80.0
1 鈴木 NaN 72.0
2 高橋 31.0 NaN
3 田中 NaN NaN
name age score
0 佐藤 25.0 80.0
1 鈴木 NaN 72.0
2 高橋 31.0 NaN
1つ目の結果では、全項目が欠けている4行目だけが消えました。2つ目は次のthreshの例です。
thresh:値がいくつあれば残すかを決める
thresh=2は「欠損でない値が2個以上ある行を残す」という意味です。「欠損が2個以上なら削除」ではない点を取り違えやすいので注意してください。上の表は3列なので、thresh=2なら欠損が1個までの行(0・1・2行目)が残り、値がnameの1個だけの3行目と、値が1つもない4行目が消えます。
列数が多い表で「半分以上の項目が埋まっている行だけ使う」ときは、thresh=len(df.columns) // 2のように列数から計算すると意図が伝わりやすくなります。なお、threshとhowを同時に指定するとTypeErrorになります。
axis=1:欠損を含む列を削除する
axis=1(またはaxis="columns")にすると、行ではなく列を削除します。howやthreshは列単位で働きます。
import numpy as np
import pandas as pd
df = pd.DataFrame({
"name": ["佐藤", "鈴木", "高橋"],
"age": [25, np.nan, 31],
"memo": [np.nan, np.nan, np.nan],
})
print(df.dropna(axis=1))
print()
print(df.dropna(axis="columns", how="all"))
print()
print(df.dropna(axis=1, thresh=3))
実行結果:
name
0 佐藤
1 鈴木
2 高橋
name age
0 佐藤 25.0
1 鈴木 NaN
2 高橋 31.0
name
0 佐藤
1 鈴木
2 高橋
axis=1:欠損を1つでも含むageとmemoの両方が消えるaxis="columns", how="all":全部欠けているmemoだけが消えるaxis=1, thresh=3:値が3個そろっている列(name)だけが残る
アンケートの未使用の設問など、まったく使われていない列を落とすときはhow="all"を付けておくと、必要な列まで消してしまう事故を防げます。
削除した後の行番号を振り直す:ignore_index
dropna()は元の行番号(インデックス)をそのまま残すので、削除後は0, 2のように番号が飛びます。0から振り直したいときは、pandas 2.0以降ならignore_index=True、それより前のバージョンでも使える書き方ならreset_index(drop=True)です。
import numpy as np
import pandas as pd
df = pd.DataFrame({"a": [1, np.nan, 3], "b": [4, 5, 6]})
print(df.dropna())
print()
print(df.dropna(ignore_index=True))
print()
print(df.dropna().reset_index(drop=True))
実行結果:
a b
0 1.0 4
2 3.0 6
a b
0 1.0 4
1 3.0 6
a b
0 1.0 4
1 3.0 6
番号が飛んだままだと、df.loc[1]のように番号で行を取り出したときにKeyErrorになることがあります。後で番号を使う処理があるなら振り直しておきましょう。
inplace=Trueは使うべきか
inplace=Trueを付けると元のDataFrameが書き換わり、戻り値はNoneになります。
import numpy as np
import pandas as pd
df = pd.DataFrame({"a": [1, np.nan, 3]})
result = df.dropna(inplace=True)
print(result)
print(df)
実行結果:
None
a
0 1.0
2 3.0
df = df.dropna(inplace=True)と書くとdfがNoneになってしまう、というのがよくある間違いです。df = df.dropna()と代入する書き方なら、メソッドをつなげて書くこともでき、元のデータを残したまま比較することもできます。特別な理由がなければ、代入する書き方をおすすめします。
dropnaで消えない「見た目の欠損」に注意
dropna()が欠損として扱うのはNaN・None・pd.NA・NaTなどで、空文字""や空白だけの文字列、"N/A"という文字は対象外です(read_csvは既定で空欄や"N/A"、"NULL"などを読み込み時にNaNへ変換しますが、空白だけの値や、手で作ったデータ・別の経路で入った値はそのまま残ります)。
import numpy as np
import pandas as pd
df = pd.DataFrame({"city": ["東京", "", " ", "N/A", np.nan]})
print(df.dropna())
print()
cleaned = df.replace(r"^\s*$", np.nan, regex=True).replace("N/A", np.nan).dropna()
print(cleaned)
実行結果:
city
0 東京
1
2
3 N/A
city
0 東京
1つ目の結果では、空文字・空白・"N/A"の行が残っています。replace()で先にNaNへ置き換えてからdropna()すると、2つ目のようにまとめて消せます。値の置き換えはpandas replace()の使い方で詳しく解説しています。
よくあるエラーと確認のしかた
import numpy as np
import pandas as pd
df = pd.DataFrame({"a": [1, np.nan, 3]})
try:
df.dropna(how="all", thresh=1)
except TypeError as e:
print("TypeError:", e)
try:
df.dropna(subset=["x"])
except KeyError as e:
print("KeyError:", e)
実行結果:
TypeError: You cannot set both the how and thresh arguments at the same time.
KeyError: ['x']
TypeError: You cannot set both the how and thresh arguments at the same time.:howとthreshを同時に指定している。どちらか一方にするKeyError: ['x']:subsetに存在しない列名を渡している。df.columns.tolist()で列名を確認する(CSVの列名に空白が付いていることもある)
削除の前後で件数を確かめる習慣をつけると、消しすぎに気づけます。Seriesにも同じ名前のdropna()があり、欠損の要素だけを取り除きます。
import numpy as np
import pandas as pd
s = pd.Series([1.5, np.nan, 3.0, None])
print(s.dropna())
print()
df = pd.DataFrame({"a": [1, np.nan, 3], "b": [np.nan, np.nan, 6]})
print(df.isna().sum())
print(len(df), "->", len(df.dropna()))
実行結果:
0 1.5
2 3.0
dtype: float64
a 1
b 2
dtype: int64
3 -> 1
削除する前に考えたいこと
欠損のある行を消すと、残ったデータが偏ることがあります。たとえば「高齢の回答者ほど年収欄が空欄」なら、空欄の行を消すと平均年齢が下がった集計になります。削除してよいかは、欠損の数と、欠け方に偏りがないかを見て決めます。
- 欠損の数を数える:pandasで欠損値NaNを判定・カウントする方法
- 欠損のある行を抜き出して中身を見る:欠損値NaNを含む行・列を特定・抽出する方法
- 削除ではなく埋める:fillnaで欠損値を埋める方法、interpolate()で線形補間する方法
- NaN・None・pd.NAの違い:pandasの欠損値NaN・None・pd.NAの違い
- pandasを使わずNumPyの配列で同じことをする:NumPyでNaNを含む行・列を削除する方法
よくある質問
Q. dropna()で特定の列にNaNがある行だけ削除するには?
subsetに列名を渡します。df.dropna(subset=[“age”])ならage列が欠けている行だけが削除され、他の列の欠損は無視されます。列が1つなら文字列のままsubset=”age”と書くこともできます。
Q. subsetに複数の列を指定したときの動きは?
既定のhow=”any”では、指定した列のどれか1つでも欠けていれば削除します。指定した列がすべて欠けている行だけを削除したいときはhow=”all”を一緒に指定します。
Q. threshの数字は何を表していますか?
欠損でない値がいくつ以上あればその行(列)を残すか、という個数です。thresh=2なら値が2個以上ある行が残ります。欠損の個数ではない点に注意してください。また、howと同時には指定できません。
Q. dropna()したのにDataFrameが変わりません。
dropna()は既定では新しいDataFrameを返すだけで、元のデータは変わりません。df = df.dropna()のように代入してください。inplace=Trueを使う場合は戻り値がNoneになるので、df = df.dropna(inplace=True)とは書かないでください。
Q. 空文字や”N/A”の行がdropna()で消えないのはなぜですか?
dropna()が欠損として扱うのはNaN・None・pd.NAなどで、空文字や”N/A”という文字列は通常の値だからです。replace()で先にNaNに置き換えてからdropna()してください。
pandas|欠損値の扱いの関連記事
NaNの判定・削除・補完など、欠損値処理に関する記事です。
- 欠損値NaNを賢く埋める!fillnaでデータクレンジング
- 欠損値NaNを含む行・列を特定・抽出する方法
- pandasのinterpolate()の使い方|欠損値の線形補間
- NaNの除外・置換・抽出をマスターしてデータ分析の質を向上
- pandasの欠損値NaN・None・pd.NAの違い
- pandasで欠損値NaNを判定・カウントする方法
pandas全体の使い方は「pandasの使い方を初心者向けに解説」でまとめています。




