欠損値はなぜ欠けたのか:削除・補完・そのままの選び方を小さな架空データで考える
AIを使いこなすClaudeで執筆し、GPTで自動校閲・修正しています。

「欠損値は削除と補完のどちらがいいのか」という問いに、最初に答えます。どちらが正しいかは、値が欠けた理由で決まります。 理由を確かめる前に dropna() や平均での穴埋めをすると、集計結果が静かに偏ることがあります。 この記事では、欠損の理由を「無回答」「未計測」「該当なし」の3つに分けます。理由ごとに、削除・補完・そのまま残す、のどれを選ぶかを判断表にまとめました。pandasで欠損を数えるコードと、AIに相談するときの依頼文も載せています。 なお、記事中のデータはすべて説明用の例です。実在の調査や実測の結果ではありません。
先に結論:判断表
- 無回答(答えられたのに答えなかった)、例:アンケートの満足度が空欄、第一候補:欠損のまま集計し、回答率を併記する。必要なら「無回答」という区分を作る、避けたい対処:平均値で全員分を埋めて「全員の満足度」として報告する
- 未計測(測るはずが測れなかった)、例:機器の不調で待ち時間が記録されていない、第一候補:偶然の抜けなら、削除か補完を比較する。特定条件で抜けるなら原因を先に調べる、避けたい対処:理由を見ずに一律で削除する
- 該当なし(そもそも値が存在しない)、例:学生でない人の「学割額」、第一候補:欠損のまま残す、または「該当なし」区分にする。0と区別する、避けたい対処:0や平均で埋める
表の「第一候補」は、後述の考え方にもとづく編集上の目安です。データの目的が違えば結論も変わります。
理由別の考え方
無回答:答えなかったこと自体が情報かもしれない
無回答は、「たまたま空欄だった」場合と「答えにくい人ほど空欄にした」場合で意味が違います。後者だと、回答者だけで平均を出すと現実からずれます。たとえば不満の強い人ほど満足度を書かないなら、残った回答の平均は実態より高く出ます。
そのため最初にやるのは、無回答の人と回答した人で、ほかの列に違いがあるかを見ることです。年齢や利用回数の分布が大きく違うなら、単純な削除も平均補完も危険です。違いが見えない場合でも、「偏りがない」と証明されたわけではありません。報告では、回答率や欠損数を必ず併記してください。
未計測:抜け方にパターンがあるか
機器の瞬断のような偶然の抜けなら、削除による偏りが小さい可能性はあります。ただし残りの行数が減り、推定の不確かさが大きくなることがあります。抜け方や分析の目的を確かめずに、偏りが小さいとは言い切れません。
一方、「混雑して忙しいときほど記録が抜ける」のように、値そのものと抜け方が関係している場合があります。行や列を捨てると、分析に使える情報が失われます。欠損の仕組みが分からないまま削除や補完をすると偏りが残る可能性があるため、補完手法の選定より、抜けた原因を現場に確認するほうが先です。
補完する場合は、補完した行を後から区別できるようにしてください。同ドキュメントには、補完した位置を示す MissingIndicator や、補完器に指標列を付ける add_indicator=True が紹介されています。
該当なし:欠損ではなく「構造」
「学生でない人の学割額」は、測り忘れではなく、値が存在しません。ここを平均で埋めると、存在しない学割が存在したことになります。0で埋めるのも、「学生だが割引を使わなかった0円」と混ざるので避けます。
対処は、欠損のまま残して集計時に対象を絞る(学生だけの平均を出す)か、「該当なし」という区分を明示することです。集計対象を絞るときは、分母が誰なのかを文章に書いてください。
pandasで欠損を数える
補完や削除の前に、欠損の数と偏りを見ます。以下は上の説明用データを使ったコード例です。この記事を書く過程では実行していないので、手元で動かして確認してください。
import pandas as pd
# 説明用の例(架空データ)
df = pd.DataFrame({
"年齢": [23, 35, 41, None, 29, 52, 38, 27, 45, 31],
"満足度": [4, 5, None, 3, None, 4, None, 2, 5, 4], # 無回答
"待ち分": [5, 8, 12, 6, None, None, 9, 15, 7, None], # 未計測
"学生": [True, False, False, True, False,
False, True, False, False, False],
"学割額": [300, None, None, 300, None,
None, 300, None, None, None], # 該当なし
})
# 1. 列ごとの欠損数と割合
print(df.isna().sum())
print(df.isna().mean().round(2))
# 2. 満足度が無回答の人と回答した人で、ほかの列に差があるか
print(df.groupby(df["満足度"].isna())[["年齢", "待ち分"]].mean())
# 3. 「該当なし」の確認:学生でない人の学割額は全部欠損か
print(df.loc[~df["学生"], "学割額"].isna().all())
# 4. 欠損のある行だけ目視する
print(df[df.isna().any(axis=1)])このデータを手で数えると、欠損数は年齢が1、満足度が3、待ち分が3、学割額が7になるはずです。学割額の7件は、すべて学生でない人の行です。コードの出力がこれと違えば、データの読み込みか列名を確認してください。
pandasの欠損データのユーザーガイドによると、欠損の判定には isna() / notna() を使い、np.nan == np.nan のような等価比較は使えません(結果が False になります)。また、平均や標準偏差などの集計は、既定で欠損を飛ばして計算します。つまり、何も指定しなくても欠損のない値だけで平均が計算されます。削除も補完もしない「そのまま」の集計でも、集計の対象数は減ることがあります。分母を確認し、忘れずに記録してください。
同ガイドは、削除に dropna()、穴埋めに fillna()、前後の値を使う ffill() や interpolate() を挙げています(今回確認した時点のガイドはpandas 3.1.0の表示でした)。時系列の補間などは、並び順に意味があるデータ向けです。上の架空データのような独立した回答には向きません。
削除・補完・そのままの使い分け手順
- 列ごとに理由を書く。 無回答・未計測・該当なしのどれかを、データの定義書や現場の担当者に確認して一行ずつメモします。分からない列は「不明」と書きます。
- 数える。 上のコードで、欠損の数、割合、ほかの列との関係を見ます。
- 理由に合う対処を選ぶ。 判断表のとおり、該当なしは残す、無回答は回答率を併記、未計測は原因を調べてから削除か補完を決めます。
- 補完するなら記録を残す。 どの列を、何で埋め、何件に適用したかを書きます。補完済みかを示す列も付けます。
- 別の対処でも結論が変わらないか確かめる。 削除した場合と補完した場合で主要な数字が大きく動くなら、その差も報告に含めます。
機械学習で使う場合は、補完を学習データだけで学習する設計にします。scikit-learnのドキュメントでは、補完器を Pipeline に組み込む例が示されています。また、決定木系など一部の推定器は欠損を直接扱えるとされています。対応する推定器の一覧はドキュメントで確認してください。
AIに相談するときの依頼文
AIに任せるのは、列ごとの欠損理由の仮説出しと、確認すべき点の洗い出しまでです。理由の決定や、報告にどの対処を採るかの判断は、データの現場を知る人が行います。
渡す情報は、列名、型、欠損数、欠損の理由として分かっていること、分析の目的です。個人が特定できる実データや機密の値は貼らず、説明用の値に置き換えてください。サービスによってデータの扱いの条件は異なるので、入力前に利用規約と設定を確認してください。
そのまま使える依頼文の例です。
データ分析の初心者です。次の欠損について、対処の候補を教えてください。
目的:来店客の平均満足度を月次で報告したい
列と欠損:
- 満足度(1〜5):10件中3件が空欄。アンケートの任意回答
- 待ち時間(分):10件中3件が空欄。計測機器の記録漏れの可能性
- 学割額(円):10件中7件が空欄。学生でない人は対象外
お願い:
1. 各列の欠損理由として考えられるものを、確認すべき質問付きで挙げてください
2. 削除・補完・そのまま残す、のそれぞれのリスクを列ごとに表で示してください
3. 私が確認すべきことを最後に箇条書きにしてください
断定せず、分からないことは分からないと書いてください。返ってきた回答は、次の点を人が確認します。
- 欠損の理由が、実際の現場の事情と合っているか
- 提案された補完方法が、該当なしの列に使われていないか
- コードが提示された場合は、手元の小さなデータで実行して、数え方が合っているか
よくある迷いどころ
欠損が数%しかないなら削除でよいか。 割合が小さくても、欠けた行が特定の層に偏っていれば結果は偏ります。先に、上の手順2で偏りを見てください。
空欄ではなく「0」や「不明」「-」と入っている場合は。 pandasは、これらを自動で欠損とは見なしません。pandasのガイドには、特定の値を欠損に置き換える replace の例があります。ただし、0を欠損にしてよいかは、その0が「測定して0だった」のか「入力できず0にした」のかを確認してから決めます。
平均補完は使ってはいけないのか。 禁止ではありません。ただし、全員に同じ値が入るため、ばらつきが実際より小さく見えます。平均や分布を報告する場合は、補完前後の数字を並べて見せるのが安全です。これは編集上の注意であり、手法の優劣を一般に決めるものではありません。
実践メモ:最初の15分でやること
手元のデータで、まず次の3つを実行してください。
- df.isna().sum() で欠損の多い列を特定する
- 欠損の多い列ごとに、無回答・未計測・該当なしのどれかを一行で書く
- 判断表の第一候補を試し、削除した場合との差を記録する
理由が分からない列が残るなら、その列の扱いを決める前に、データの作成者へ確認する質問を作ってください。

