欠測値(けっそくち)とは、本来は観測・記録されるはずだったのに値が入っていないデータのことです。アンケートの無回答、センサーの取得漏れ、臨床試験の途中脱落などで生じます。データ分析で使う「欠損値」と同じ意味で、英語ではどちらも missing data(missing value)です。欠測を含むデータをそのまま集計すると、平均や回帰係数が偏ることがあります。この記事では、欠測の3つの仕組み(MCAR・MAR・MNAR)、リストワイズ削除とペアワイズ削除の違い、平均値代入と多重代入の差を、Python と R で実際に計算した結果を使って説明します。
まとめ:欠測値の意味と対処法の選び方
- 欠測値と欠損値は同じものです。統計学・公的統計・臨床試験では「欠測」、機械学習や pandas の実務では「欠損」と呼ぶことが多いだけです。
- 欠測の仕組みはMCAR(完全にランダム)・MAR(観測できる変数で説明できる)・MNAR(欠けた値そのものに依存)の3つに分かれ、どれに当たるかで使える対処法が変わります。
- 欠測値のあるケースを丸ごと除く方法がリストワイズ削除、計算ごとに使えるデータだけを使う方法がペアワイズ削除です。pandas の
corr()や SPSS の相関は、指定しなくてもペアワイズ削除で計算されます。 - 平均値代入は標準偏差を過小評価します。目的変数を平均値で埋めると回帰の傾きもゼロに近づき、今回の実測では0.99が0.60まで縮みました。
- MAR なら多重代入法か完全情報最尤推定(FIML)を使います。MNAR では、欠測の仕組みに追加の仮定を置いて解析し、その仮定を変えて結論が動かないかを感度分析で確かめます。
欠測値の意味と欠損値との違い
欠測値は、調査・測定・記録の途中で値が得られなかった状態を指します。Excel では空欄、データベースでは NULL、pandas では NaN、R では NA、SPSS ではピリオド(.)で表示されます。見た目はただの空欄でも、分析では「値が無い」という情報を持つ特別な値として扱います。
欠測値と欠損値の呼び分け(分野ごとの慣習)
欠測値と欠損値は同じ概念です。訳語が2通りあるだけで、どちらを使っても誤りではありません。
| 用語 | よく使う分野 | 例 |
|---|---|---|
| 欠測値(けっそくち) | 統計学・生物統計・公的統計・臨床試験 | ICH E9(R1) の訳語「欠測データ」 |
| 欠損値(けっそんち) | 機械学習・データ分析・データベース | pandas の欠損値処理 |
| 補定(ほてい) | 公的統計 | imputation(代入)の訳語 |
公的統計では、欠測を推定値で埋める処理を「補定」と呼びます。統計センターの製表技術参考資料30(2015年6月)は「『補定』とは、“imputation”の訳語である」と定義しており、2016年経済センサス‐活動調査では未回答の経理項目に「比率補定(ratio imputation)」が使われました。「失測」と表記されることもありますが、統計の用語としては「欠測」が使われます。
欠測として扱わない値:非該当・「わからない」・存在しない測定値
空欄がすべて欠測とは限りません。分析の前に、次の3つを欠測と分けておきます。
- 非該当:子どもがいない回答者の「子どもの年齢」欄のように、もともと値が存在しない項目です。
- 「わからない」「答えたくない」:回答の一つとして集計するのか、欠測として扱うのかを先に決めます。SPSS では、こうしたコード(例:99)をユーザー欠損値として宣言できます。1変数に指定できる個別の値は3つまでで、数値変数なら範囲でも指定できます。既定ではシステム欠損値(ピリオド)と同じ扱いになりますが、元のコードはデータに残るため、拒否と無回答を後から区別できます。
- 存在しない測定値:臨床試験のガイドライン ICH E9(R1) は「死亡後の測定値は存在しない」と明記し、欠測データを「ある推定対象(estimand)の解析に意味があったはずだが収集されなかったデータ」と定義しています。日本では2024年6月20日付の厚生労働省通知(医薬薬審発0620第1号)で周知されました。治療中止のような出来事は欠測ではなく、何を推定したいかの定義で扱います。
欠測が起きる仕組み:MCAR・MAR・MNARの3分類
対処法を選ぶ前に、なぜ欠けたのかを考えます。この3分類は、Rubin の論文「Inference and Missing Data」(Biometrika 第63巻第3号、1976年)を起点に、Little と Rubin の教科書『Statistical Analysis with Missing Data』(第3版は2019年)で体系化されたものです。
| 分類 | 欠測の起こりやすさが決まるもの | 例 |
|---|---|---|
| MCAR | 何とも関係しない | 試験管を割った・通信エラー |
| MAR | 観測できている他の変数 | 高齢者ほど体重欄が空欄 |
| MNAR | 欠けている値そのもの | 高収入の人ほど年収を答えない |
MCAR(完全にランダムな欠測)
MCAR(Missing Completely At Random)は、欠けるかどうかが観測値とも未観測値とも無関係な状態です。残ったデータは元のデータの無作為な一部なので、削除しても平均や相関に系統的な偏りは出ません。失うのは標本数と検出力だけです。
MAR(観測できる変数で説明できる欠測)
MAR(Missing At Random)は、欠けやすさが観測済みの変数で説明できる状態です。たとえば年齢が高い回答者ほど体重を書かない場合、年齢をそろえて見れば欠測はランダムに見えます。名前に反して完全なランダムではありません。欠測に関係する観測済みの変数を含め、代入モデルや分析モデルを適切に指定できれば、多重代入法や FIML で偏りを抑えられます。
MNAR(欠けた値そのものに依存する欠測)
MNAR(Missing Not At Random)は、欠ける理由が欠けた値そのものにある状態です。症状の重い患者ほど来院できず測定値が欠ける、といった場合です。観測データだけでは欠けた値の分布を一意に特定できません。通常の削除や MAR を仮定した代入では偏る可能性があり、MNAR を扱う追加の仮定が必要です。
尤度に基づく推論では、MAR(MCARを含む)に加えて、データモデルと欠測モデルのパラメータが分離できる場合に、欠測機構を「無視できる(ignorable)」と扱えます。注意したいのは、MAR と MNAR は手元のデータだけでは区別できない点です。どちらかは、調査の設計や現場の知識から判断します。
欠測率の求め方とLittleのMCAR検定
欠測率は「欠測しているセルの数 ÷ 全体のセルの数」で、まず変数(列)ごとに求めます。あわせて、どれか1つでも欠けている行の割合(不完全ケースの割合)も見ておきます。この行単位の割合から、リストワイズ削除で失う行数を把握できます。多重代入のセット数を決める目安にもなりますが、欠測情報の割合や必要な推定精度も考慮します。pandas なら df.isna().mean() で列ごと、df.isna().any(axis=1).mean() で行単位の割合が出ます。
何%までなら許容できるかという公的な基準はありません。欠測率が数%でも MNAR なら偏りは残り、40%でも MCAR なら削除で偏りは出ません(後述の実測を参照)。量より仕組みを先に見ます。ただし、半数以上が欠けている変数は、埋めても大半が推定値になるため、分析に入れるかどうかから考え直します。
MCAR かどうかを確かめる検定に、Little の MCAR 検定(Journal of the American Statistical Association 第83巻、1988年)があります。帰無仮説は「データは MCAR である」で、有意なら MCAR とは言えません。ただし有意でなくても MCAR の証明にはならず、MAR と MNAR の区別もできません。
リストワイズ削除とペアワイズ削除の違い
削除法は、欠測を含むデータを分析から除く方法です。実装は簡単ですが、どちらの削除がどこで使われているかを知らないまま結果を読むと、行数の食い違いや説明できない相関に悩むことになります。
リストワイズ削除の対象行・標本数への影響・適用条件
リストワイズ削除は、分析に使う変数のどれか1つでも欠けている行(ケース)を丸ごと除く方法です。完全ケース分析(complete case analysis)とも呼びます。試験問題の「欠損値のあるサンプルを除外して考える方法」は、このリストワイズ法を指します。
欠点は標本が急に減ることです。10個の変数がそれぞれ独立に5%ずつ欠けていると、全部そろう行は 0.95の10乗=約60%しか残りません。偏りについては、MCAR なら生じません。MAR では推定したい量によって分かれ、平均は偏りますが、欠測が回帰モデルに入っている説明変数だけで決まるなら、その回帰係数は偏りません(後述の実測で確認します)。
ペアワイズ削除の計算単位と相関行列の不整合
ペアワイズ削除は、計算ごとに必要な変数がそろっている行だけを使う方法です。利用可能ケース分析(available case analysis)とも呼びます。相関行列なら、各セルをその2変数がそろった行だけで計算します。リストワイズ削除よりデータを多く使えますが、セルごとに使う行が違うため、行列全体としてつじつまが合わなくなることがあります。極端な例を pandas 3.0.6 で計算しました。
import numpy as np
import pandas as pd
nan = np.nan
a = pd.DataFrame({
"A": [1, 2, 3, 4, 5, 6, nan, nan, nan],
"B": [1, 2, 3, nan, nan, nan, 1, 2, 3],
"C": [nan, nan, nan, 1, 2, 3, 3, 2, 1],
})
c = a.corr() # 既定でペアワイズ削除になる
print(c)
print(np.linalg.eigvalsh(c.to_numpy())) # 固有値に負が出る=相関行列として成り立たない
A B C
A 1.0 1.0 1.0
B 1.0 1.0 -1.0
C 1.0 -1.0 1.0
[-1. 2. 2.]
A と B、A と C が完全な正の相関なのに、B と C が完全な負の相関になっています。3つの変数でこの組み合わせは起こりえず、固有値に −1 が出ます。正定値でない相関行列は、因子分析や構造方程式モデリング、多変量の回帰にそのまま渡すと推定が止まる原因になります。
ツールの既定で使われる削除法
多くのツールは、指定しなければどちらかの削除法を黙って使います。同じデータでも、相関と回帰で分析に使う行数が変わるのはこのためです。各公式ドキュメントと実行結果で確認した既定を並べます。
| ツール・関数 | 欠測があるときの既定 |
|---|---|
pandas DataFrame.corr() |
ペアワイズ削除 |
pandas mean() など |
欠測を飛ばして計算 |
R cor() |
NA を返す |
R lm() |
リストワイズ削除 |
statsmodels smf.ols() |
リストワイズ削除 |
statsmodels sm.OLS() |
処理なし(x の NaN はエラー・y だけなら係数が NaN) |
scikit-learn LinearRegression |
エラー |
| SPSS 相関(CORRELATIONS) | ペアワイズ削除 |
| SPSS 回帰(REGRESSION) | リストワイズ削除 |
pandas の DataFrame.corr は「NA/null 値を除いて列のペアごとに相関を計算する」と説明されており、ペアに必要な最小観測数 min_periods の既定は1です。R の cor() は use = "everything" が既定で、欠測が1つでもあると NA になります。lm() は options("na.action") に従い、初期設定の na.omit で欠測行を落とします。SPSS の REGRESSION の MISSING サブコマンドは、省略すると LISTWISE になります。Python 側は次のコードで確かめました。
import numpy as np
import pandas as pd
import statsmodels.api as sm
import statsmodels.formula.api as smf
from sklearn.linear_model import LinearRegression
df = pd.DataFrame({"x": [1, 2, 3, 4, np.nan], "y": [2, np.nan, 6, 8, 10]})
print(df["y"].mean(), df["y"].mean(skipna=False)) # 6.5 と nan
print(smf.ols("y ~ x", data=df).fit().nobs) # 3.0(欠測行を落として推定)
for fit in (lambda: sm.OLS(df["y"], sm.add_constant(df["x"])).fit(),
lambda: LinearRegression().fit(df[["x"]], df["y"])):
try:
fit()
except Exception as e:
print(type(e).__name__) # MissingDataError と ValueError
相関表と回帰の表を並べる報告書では、相関はペアワイズ、回帰はリストワイズという組み合わせになりがちです。表ごとに N を書くか、先に分析用データを1つに確定してから両方を計算します。
補完法:平均値代入の問題と多重代入法
補完法(代入法、imputation)は、欠けた箇所を推定値で埋めて完全なデータに戻す方法です。標本を減らさずに済む反面、埋め方を誤ると、ばらつきを小さく見せたり、推定の精度を実際より高く見せたりします。
単一代入(平均値代入・回帰代入・LOCF)の限界
単一代入は、欠測1つに値を1つだけ入れる方法です。平均値・中央値で埋める、回帰式の予測値で埋める、時系列で直前の値を引き継ぐ(LOCF:last observation carried forward)などがあります。
平均値代入は、埋めた値がすべて分布の中心に集まるため、標準偏差が小さくなり、他の変数との関係も弱まります。平均値そのものは変わらないので、平均だけを見ていると気づきません。
LOCF については、米国 National Research Council の報告書『The Prevention and Treatment of Missing Data in Clinical Trials』(2010年)が「脱落後に参加者のアウトカムが変化しないという強い仮定」に立つと指摘し、仮定を科学的に正当化できない限り、LOCF のような単一代入を主たる解析方法にすべきでないと勧告しています。
多重代入法(MICE)の手順とRubinのルール
多重代入法(multiple imputation)は、欠測を1回だけ埋めるのではなく、もっともらしい値を何通りも生成して m 個の完全データを作り、それぞれで同じ分析をしてから結果を統合する方法です。値の不確かさを最後の標準誤差に反映できるため、単一代入のように精度を過大に見せません。変数ごとに回帰モデルを立てて順番に代入を繰り返す方式を MICE(Multivariate Imputation by Chained Equations、連鎖方程式による多変量代入)と呼びます。
統合には Rubin のルールを使います。m 個の推定値の平均を最終の推定値とし、全分散は T = Ū + (1 + 1/m)B で求めます。Ū は各補完データで求めた推定値の分散(標準誤差の二乗)の平均、B は m 個の推定値の標本分散です。R の mice パッケージの pool() もこの式で計算しています。
代入回数 m は、昔は3〜5回が定番でしたが、今は欠測の量に合わせて決めます。van Buuren の『Flexible Imputation of Missing Data』は、White・Royston・Wood(2011)が採った目安として「代入回数は不完全なケースの割合(%)と同程度にする」を紹介しています(欠測情報の割合が0.5までの場合)。不完全な行が28%なら m=28 前後です。点推定だけが目的なら m=5〜20 で足りるとも書かれています。
FIML(完全情報最尤推定)の仕組みと多重代入との違い
FIML(full information maximum likelihood)は、値を埋めずに、各行で観測されている部分だけを使って尤度を計算し、パラメータを直接推定する方法です。多重代入と同じく MAR を前提にします。たとえば構造方程式モデリング(SEM)の R パッケージ lavaan は FIML に対応しています。代入値を乱数で生成する方式ではないため、多重代入に伴うモンテカルロ変動はありません。一方で、欠測の原因になっている補助変数を使うには、分析モデルの側に組み込む工夫が要ります。分析モデルと切り離して補助変数を自由に入れられる点では、多重代入の方が扱いやすい方法です。
シミュレーション:欠測の仕組み別に見た3つの対処法の推定結果
同じ1万件のデータ(y=2+x+誤差、真の平均2・傾き1)から y を約40%欠けさせ、MCAR・MAR・MNAR の3通りで、リストワイズ削除・平均値代入・多重代入(scikit-learn の IterativeImputer で10セット)の結果を比べました。Python 3.12.13、pandas 3.0.6、scikit-learn 1.9.1 で実行しています。
import numpy as np
import pandas as pd
from sklearn.experimental import enable_iterative_imputer # noqa: F401
from sklearn.impute import IterativeImputer
rng = np.random.default_rng(0)
n = 10000
x = rng.normal(size=n)
y = 2 + 1.0 * x + rng.normal(size=n) # 真の値:平均2・傾き1
def p(z): # 欠測確率(最大0.8)
return 0.8 / (1 + np.exp(-2 * z))
masks = {
"MCAR": rng.random(n) < 0.4, # 値と無関係に40%
"MAR": rng.random(n) < p(x), # 観測できる x が大きいほど欠ける
"MNAR": rng.random(n) < p(y - 2), # y 自身が大きいほど欠ける
}
def summarize(d):
b = np.polyfit(d["x"], d["y"], 1)[0] # y を x で回帰した傾き
return round(d["y"].mean(), 3), round(d["y"].std(), 3), round(b, 3)
rows = [["欠測なし", "-", "-", *summarize(pd.DataFrame({"x": x, "y": y}))]]
for name, miss in masks.items():
df = pd.DataFrame({"x": x, "y": np.where(miss, np.nan, y)})
rate = f"{df['y'].isna().mean():.0%}"
rows.append([name, rate, "リストワイズ削除", *summarize(df.dropna())])
rows.append([name, rate, "平均値代入", *summarize(df.fillna({"y": df["y"].mean()}))])
res = []
for k in range(10): # 10セットの多重代入
imp = IterativeImputer(sample_posterior=True, random_state=k)
res.append(summarize(pd.DataFrame(imp.fit_transform(df), columns=df.columns)))
# 平均・SD・傾きの記述的比較のみ。標準誤差や信頼区間の統合は行っていない。
rows.append([name, rate, "多重代入(m=10)", *np.round(np.mean(res, axis=0), 3)])
print(pd.DataFrame(rows, columns=["欠測", "欠測率", "対処", "yの平均", "yのSD", "傾き"]).to_string(index=False))
欠測 欠測率 対処 yの平均 yのSD 傾き
欠測なし - - 2.009 1.398 0.986
MCAR 40% リストワイズ削除 2.020 1.408 0.994
MCAR 40% 平均値代入 2.020 1.088 0.596
MCAR 40% 多重代入(m=10) 2.020 1.408 0.995
MAR 40% リストワイズ削除 1.598 1.330 0.980
MAR 40% 平均値代入 1.598 1.026 0.479
MAR 40% 多重代入(m=10) 2.013 1.398 0.984
MNAR 41% リストワイズ削除 1.360 1.244 0.864
MNAR 41% 平均値代入 1.360 0.958 0.453
MNAR 41% 多重代入(m=10) 1.650 1.281 0.866
読み取れることは4つあります。
- この MCAR の例では削除後の点推定も近い:標本数と推定精度は低下しますが、リストワイズ削除の平均2.020・傾き0.994は、欠測前の2.009・0.986とほぼ同じです。
- 目的変数の平均値代入は、どの仕組みでも傾きを縮める:MCAR でも傾きは0.596、標準偏差は1.088まで縮みました。
- MAR では、多重代入だけが平均を戻す:削除と平均値代入の平均1.598に対し、多重代入は2.013です。一方、削除後の傾きは0.980でした。このモデルでは欠測が説明変数 x だけで決まるため、回帰係数は理論上不偏ですが、1回の計算結果だけで不偏性を確認したわけではありません。
- MNAR は、MAR を仮定した多重代入では戻らない:平均は1.650、傾きは0.866で、削除より少し良い程度です。MNAR が疑われるときは、MAR を仮定した多重代入の結果だけで安心してはいけません。
この比較は、欠測の起こり方を知っている人工データだから作れるものです。実データでは仕組みがわからないので、MAR を仮定した結果と、MNAR を想定して欠けた値を少しずらした結果を並べ、結論が変わらないかを確かめる感度分析が必要になります。
Python・R・SPSSで欠測値を扱う手順
流れはどのツールでも、欠測の量とパターンを数える、仕組みの見当をつける、代入して分析し統合する、の順です。
Pythonによる欠測の集計・多重代入・結果の統合
Pandas では isna() で欠測を数え、dropna() で削除、fillna() で単一代入します。多重代入から Rubin のルールによる統合まで一度に行うなら、statsmodels の MICE が使えます。statsmodels 0.15.0 で実行した例です。
import numpy as np
import pandas as pd
import statsmodels.api as sm
import statsmodels.formula.api as smf
from statsmodels.imputation import mice
rng = np.random.default_rng(1)
n = 1000
df = pd.DataFrame({"x1": rng.normal(size=n), "x2": rng.normal(size=n)})
df["y"] = 2 + df["x1"] + 0.5 * df["x2"] + rng.normal(size=n)
miss = rng.random(n) < 0.6 / (1 + np.exp(-2 * df["x1"])) # x1 が大きいほど欠ける(MAR)
df_full = df.copy()
df.loc[miss, "y"] = np.nan
print(df.isna().sum().to_dict()) # 列ごとの欠測数
print(round(df.isna().any(axis=1).mean(), 3)) # 不完全な行の割合(m の目安に使う)
imp = mice.MICEData(df, rng=np.random.default_rng(0)) # 連鎖方程式による代入(既定は予測平均マッチング)
result = mice.MICE("y ~ x1 + x2", sm.OLS, imp).fit(n_burnin=10, n_imputations=20)
print(result.summary()) # Rubin のルールで統合済み
print(smf.ols("y ~ x1 + x2", df_full).fit().params.round(3).to_dict()) # 欠測前
print(smf.ols("y ~ x1 + x2", df).fit().params.round(3).to_dict()) # リストワイズ削除
{'x1': 0, 'x2': 0, 'y': 282}
0.282
Results: MICE
=============================================================
Method: MICE Sample size: 1000
Model: OLS Scale 0.97
Dependent variable: y Num. imputations 20
-------------------------------------------------------------
Coef. Std.Err. t P>|t| [0.025 0.975] FMI
-------------------------------------------------------------
Intercept 1.9993 0.0374 53.4256 0.0000 1.9260 2.0727 0.3052
x1 0.9190 0.0385 23.8590 0.0000 0.8435 0.9945 0.3272
x2 0.4609 0.0358 12.8630 0.0000 0.3907 0.5311 0.2800
=============================================================
{'Intercept': 2.019, 'x1': 0.972, 'x2': 0.474}
{'Intercept': 1.998, 'x1': 0.929, 'x2': 0.466}
FMI 列は欠測情報の割合(fraction of missing information)で、0.28〜0.33 でした。不完全な行が28%なので、m は20〜30回が目安になります。y だけが欠け、欠測が x1 で決まる MAR なので、x1 の係数は多重代入0.919・リストワイズ削除0.929とほぼ同じです。多重代入が削除より効くのは、説明変数の側に欠測があるときや、平均・分布そのものを推定したいときです。
scikit-learn の IterativeImputer は、1.9.1 でも experimental(実験的機能)の扱いで、from sklearn.experimental import enable_iterative_imputer を先に書かないと読み込めません。既定の sample_posterior=False では毎回同じ値が入る単一代入になるので、多重代入にするには sample_posterior=True にして random_state を変えながら複数回実行し、統合は自分で行います。時系列データの欠損補間は、前後の値を使う専用の手順があるので時系列データの前処理を参照してください。
Rのmiceによる多重代入と回帰結果の統合
R では欠測は NA で表され、多重代入は mice パッケージが定番です。Docker の rocker/r2u:noble イメージ上の R 4.6.1 と mice 3.19.0 で実行しました。
suppressMessages(library(mice))
cat("R", R.version.string, " mice", as.character(packageVersion("mice")), "\n")
cat("na.action option:", getOption("na.action"), "\n")
d <- data.frame(x = c(1, 2, 3, 4, NA), y = c(2, NA, 6, 8, 10))
print(try(cor(d$x, d$y)))
print(cor(d$x, d$y, use = "complete.obs"))
fit0 <- lm(y ~ x, data = d); cat("lm nobs:", nobs(fit0), "\n")
set.seed(1)
n <- 1000; x1 <- rnorm(n); x2 <- rnorm(n); y <- 2 + x1 + 0.5 * x2 + rnorm(n)
y[x1 > 0.3 & runif(n) < 0.7] <- NA
df <- data.frame(y, x1, x2)
cat("missing y:", sum(is.na(df$y)), "\n")
# 手順確認用に m = 5 とする。本解析では代入回数を増やして結果の安定性を確認する。
imp <- mice(df, m = 5, method = "pmm", seed = 123, printFlag = FALSE)
fit <- with(imp, lm(y ~ x1 + x2))
result <- pool(fit)
print(summary(result))
print(md.pattern(df, plot = FALSE))
R R version 4.6.1 (2026-06-24) mice 3.19.0
na.action option: na.omit
[1] NA
[1] 1
lm nobs: 3
missing y: 261
term estimate std.error statistic df p.value
1 (Intercept) 2.018942 0.03648532 55.33573 73.18887 1.809350e-61
2 x1 1.060061 0.03708116 28.58758 42.66831 1.852035e-29
3 x2 0.508594 0.03542072 14.35866 65.25670 7.124516e-22
x1 x2 y
739 1 1 1 0
261 1 1 0 1
0 0 261 261
cor() は既定で NA を返し、use = "complete.obs" を付けるとリストワイズ削除で計算します。ペアワイズ削除にしたいときは use = "pairwise.complete.obs" です。md.pattern() の表は、欠測パターンごとの行数を数えたもので、この例では y だけが欠けた行が261行ありました。pool() の出力にある df は、Barnard–Rubin の小標本調整を適用した自由度です。
SPSS(システム欠損値・ユーザー欠損値と多重代入)
SPSS には2種類の欠損値があります。数値変数に文字が入っている、0で割ったなど、有効な値が作れないときに自動で入るのがシステム欠損値(ピリオド表示)です。「99=無回答」のように利用者が宣言するのがユーザー欠損値で、変数ビューの「欠損値」欄か MISSING VALUES コマンドで指定します。
削除法は手続きごとに既定が違います。前述のとおり相関(CORRELATIONS)はペアワイズ、回帰(REGRESSION)はリストワイズです。回帰では /MISSING=PAIRWISE や MEANSUBSTITUTION(平均値で置換)も選べますが、平均値置換は前章の理由で避けます。多重代入は Missing Values オプションの Multiple Imputation メニューで、欠測パターンの分析、代入、代入後のデータセットでの分析と統合まで行えます。
欠測値の対処法を選ぶ判断表と避けたい処理
実測と一次資料を踏まえて、選び方を表にまとめます。
| 状況 | 推奨 | 避ける |
|---|---|---|
| MCAR・欠測が少ない | リストワイズ削除 | 平均値代入 |
| MAR・平均や分布を推定 | 多重代入・FIML | リストワイズ削除 |
| MAR・目的変数だけ欠測(説明変数で決まる) | リストワイズ削除も可 | 平均値代入 |
| MAR・説明変数に欠測 | 多重代入 | リストワイズ削除 |
| MNAR の疑い | 感度分析 | 多重代入だけで結論 |
| 臨床試験の脱落 | estimand を先に定義 | LOCF |
はっきり避けたいのは次の3つです。1つ目は、欠測を数えずに相関と回帰を出し、表ごとに N が違うことに気づかないままにすることです。2つ目は、とりあえず平均値で埋めることです。平均は合っていても、ばらつきと関係の強さが縮み、検定や回帰の結論が変わります。3つ目は、多重代入をしただけで偏りが消えたと考えることです。MNAR に対して MAR を仮定した代入を行うと、偏りが残る可能性があります。
欠測は、分析の段階よりローデータの整形段階で見つけた方が手戻りが少なく済みます。定期的に集計するデータなら、項目ごとの欠測率を毎回出して推移を監視しておくと、入力画面の変更やシステム連携の不具合による急な欠測増加にすぐ気づけます。こうした集計と監視の仕組みは、BIツール導入支援の範囲で設計できます。
よくある質問
欠測値と欠損値は違うものですか?
同じものです。どちらも missing data(missing value)の訳語で、統計学や公的統計、臨床試験では「欠測値」、機械学習や pandas の実務では「欠損値」と呼ぶことが多いだけです。
欠損値のあるサンプルを除外して分析する方法は何と呼びますか?
リストワイズ削除(リストワイズ法、完全ケース分析)です。分析に使う変数のどれか1つでも欠けている行を丸ごと除きます。計算ごとに使える行だけを使う方法はペアワイズ削除と呼びます。
欠測率は何%まで許容されますか?
決まった基準はありません。欠測率が低くても MNAR なら偏りは残り、高くても MCAR なら削除で偏りは出ません。割合より欠測の仕組みを先に確認します。半数以上が欠けている変数は、分析に入れるかどうかから見直します。
欠測値を平均値で埋めてもよいですか?
おすすめしません。平均値は変わりませんが、標準偏差が小さくなり、他の変数との相関も弱まります。今回の実測では、目的変数を平均値で埋めると、欠測40%の MCAR で回帰の傾きが0.99から0.60に縮みました。埋めるなら多重代入法を使います。
MCAR・MAR・MNARはどう見分けますか?
MCAR かどうかは Little の MCAR 検定で確かめられますが、有意でなくても MCAR の証明にはなりません。MAR と MNAR は手元のデータでは区別できないため、欠測が起きた経緯の知識で判断し、MNAR の可能性が残るなら感度分析を行います。