EP.17 で、欠損を埋める手法をカタログとして整理しました。この回はその中の1つ、 を扱います。
「1つの値で埋めない」という発想の手法です。なぜそれが必要なのかから始めます。
1. 1つの値で埋めると何が起きるか
欠損を平均で埋めるのは最も手軽な方法です。ただし、埋めた瞬間に「その値が正しい」という情報が加わってしまいます。
| 埋め方 | 何が起きるか |
|---|---|
| 平均で埋める | ばらつきが実際より小さくなる(全員が同じ値) |
| 中央値で埋める | 同上 |
| 予測値で埋める | 予測の誤差が無いことになる |
| 多重代入 | 不確かさが結果まで残る |
1行目の影響は、思っているより大きいことがあります。ばらつきが小さく見えると、統計的な検定で差が出やすくなります。実際には差がないのに、あるように見えてしまう。
import numpy as np
rng = np.random.default_rng(42)
# 本来のデータ(平均50、標準偏差10)true_values = rng.normal(50, 10, 1000)
for missing_rate in [0.0, 0.2, 0.4, 0.6]: data = true_values.copy() n_missing = int(len(data) * missing_rate) idx = rng.choice(len(data), n_missing, replace=False)
observed = np.delete(data, idx) # 観測できた分 filled = data.copy() filled[idx] = observed.mean() # 平均で埋める
print(f"欠損 {missing_rate:4.0%}: " f"本来の標準偏差 {true_values.std():5.2f} → " f"埋めた後 {filled.std():5.2f}")実行すると、欠損率が上がるほど標準偏差が縮むことが分かります。40%欠損なら、ばらつきは本来の4分の3程度まで縮みます。データの量は保たれていますが、性質は変わっています。これは という手法そのものの問題ではなく、1つの値に決めてしまうことから生じる性質です。
欠損行を削除すれば件数が減るので、「データが減った」ことは分かります。しかし埋めると件数はそのままなので、何かを失ったことに気づけません。失われているのは、ばらつきの情報です。
2. 多重代入の考え方
多重代入 の発想は単純です。1通りに決めず、複数のもっともらしい値で埋めたデータを作り、それぞれで分析して結果を統合する。
- 1欠損を埋めたデータセットを、複数作る — 埋める値は毎回少しずつ違う
- 2それぞれに対して、同じ分析を行う — 平均を出す、回帰する、など
- 3結果を統合する — 推定値の平均と、ばらつきをまとめる
要点は3番目です。統合するとき、「各回の結果のばらつき」も考慮に入れます。埋め方によって結果が大きく変わるなら、それは推定が不確かだということ。その不確かさが、最終的な結果に反映されます。逆に、埋め方を変えても結果がほぼ同じなら、補完の影響は小さいと判断できます。この判断ができること自体が、この手法の利点です。
| ばらつきの種類 | 何を表すか |
|---|---|
| 各回の中でのばらつき | 通常のデータのばらつき |
| 各回の間でのばらつき | 埋め方による不確かさ |
| 統合後のばらつき | 両方を合わせたもの |
3. 実装してみる
考え方を、そのままコードにします。専用のライブラリもありますが、仕組みを理解するために手で書きます。
import numpy as np
def multiple_imputation_mean(data, n_imputations=10, rng=None): """欠損を含むデータの平均を、不確かさとともに推定する。""" rng = rng or np.random.default_rng(0)
observed = data[~np.isnan(data)] missing_idx = np.where(np.isnan(data))[0]
estimates = [] variances = []
for _ in range(n_imputations): filled = data.copy() # 観測値の分布から引いて埋める(毎回違う値になる) filled[missing_idx] = rng.normal( observed.mean(), observed.std(), len(missing_idx) ) estimates.append(filled.mean()) variances.append(filled.var(ddof=1) / len(filled))
estimates = np.array(estimates) variances = np.array(variances)
# 各回の中のばらつき within = variances.mean() # 各回の間のばらつき(埋め方による不確かさ) between = estimates.var(ddof=1) # 統合(Rubin の規則) total = within + (1 + 1 / n_imputations) * between
return { "推定値": estimates.mean(), "標準誤差": np.sqrt(total), "うち埋め方由来": np.sqrt((1 + 1 / n_imputations) * between), }`between`(各回の間のばらつき)が、この手法の核心です。平均で埋める方式では、この項がゼロになります。つまり「埋め方に不確かさはない」と主張していることになります。
import numpy as np
rng = np.random.default_rng(42)
true_values = rng.normal(50, 10, 500)data = true_values.copy()missing_idx = rng.choice(len(data), 150, replace=False) # 30% 欠損data[missing_idx] = np.nan
observed = data[~np.isnan(data)]
# 方法1: 平均で埋めるsingle = data.copy()single[np.isnan(single)] = observed.mean()se_single = single.std(ddof=1) / np.sqrt(len(single))
# 方法2: 多重代入result = multiple_imputation_mean(data, n_imputations=20, rng=np.random.default_rng(1))
print(f"本来の平均 : {true_values.mean():.3f}")print(f"平均で埋めた場合: 推定 {single.mean():.3f} 標準誤差 {se_single:.3f}")print(f"多重代入の場合 : 推定 {result['推定値']:.3f} " f"標準誤差 {result['標準誤差']:.3f}")print(f" (うち埋め方由来 {result['うち埋め方由来']:.3f})")推定値そのものは大きく変わりません。変わるのは標準誤差で、多重代入のほうが大きく出ます。これは精度が悪いのではなく、不確かさを正しく表しているということです。単一の値で埋めた場合の狭い標準誤差は、実態より自信があるように見せているだけです。
4. 使うべき場面、そうでない場面
手間がかかる手法なので、必要な場面を見極めます。
| 目的 | 多重代入 | 理由 |
|---|---|---|
| 推定値の信頼区間を示す | 使う | 不確かさが本質的 |
| 統計的な検定を行う | 使う | 誤った有意差を防ぐ |
| 集計値を報告する | 使う価値がある | 幅を示せる |
| 機械学習の予測 | 通常は不要 | 単純な補完で足りることが多い |
| 欠損が極めて少ない | 不要 | 影響が小さい |
| 欠損に規則性がある | 注意 | そもそも埋めてよいか(EP.17) |
最下行が重要です。EP.17 で扱ったとおり、欠損が発生する仕組みによっては、埋めること自体が誤りを生みます。「回答したくない人が回答していない」なら、観測値から埋めると偏ります。手法の選択以前の問題です。
4行目は誤解されやすい点です。予測モデルの前処理としては、多重代入の利点が活きにくい。最終的に1つの予測値を出すなら、補完の不確かさを持ち越す先がないためです。目的で使い分けてください。
5. 実務での注意点
使うときに気をつける点を挙げます。
- 分析に使う変数を、補完にも含める — 含めないと関係が薄まる
- パターン数は結果が安定するまで増やす — 5から始めて確認
- 補完後の値が現実的か確認する — 負の年齢などが出ていないか
- 補完したことを記録に残す — どの行が推定値かを保つ(EP.17)
- 欠損の割合が高すぎるなら諦める — 半分以上なら別の手を考える
1番目が見落とされやすい。最終的な分析で使う変数は、補完のモデルにも入れる必要があります。入れないと、補完した値と他の変数の関係が薄まり、分析結果が実態より弱く出ます。
3番目も必ず確認してください。分布から引いて埋めると、理論上ありえない値が出ることがあります。年齢がマイナス、割合が100%超。範囲の制約は明示的に適用する必要があります。この確認は EP.22 で扱う と同じ考え方で、補完後のデータにも品質検査をかけるということです。
6. 何を伝えるか
最後に、結果をどう報告するかです。手法を使っても、伝え方が悪ければ意味がありません。
| 報告すること | 理由 |
|---|---|
| 欠損の割合 | 読む側が信頼度を判断できる |
| 補完の方法 | 再現性のため |
| 推定値と、その幅 | 点ではなく幅で示す |
| 補完由来の不確かさ | どれだけが補完のせいか |
| 補完しない場合の結果 | 比較できると判断しやすい |
最下行が実務で効きます。補完しなかった場合(欠損行を除いた場合)の結果も併記すると、読む側が判断できます。両方でほぼ同じなら、補完の影響は小さいと分かります。
1つの値で埋めると、ばらつきが実際より小さくなる(件数が保たれるので気づきにくい)。多重代入 は複数パターンで埋めて結果を統合し、埋め方による不確かさを結果まで持ち越す。使うのは信頼区間や検定を扱う場合で、予測が目的なら単純な補完で足りる。分析に使う変数は補完にも含める。そして補完しなかった場合の結果も併記してください。
この記事の感想を教えてください
あなたの 1 クリックで、本当にこの記事は更新されます。「もっと詳しく」「続編希望」が一定数集まった記事は、 ふくふくが 実際に内容を拡充したり続編記事を公開 します。 送信したリアクションはお使いのブラウザに記録され、再カウントされません。