論文一覧に戻る 📚 用語解説(ジャストインタイム型データサイエンス教育)
欠損値
Missing Value (NaN)
値が記録されなかった/欠けたセル。pandasではNaN。除外(dropna)or 補完(fillna)で対処。
データ前処理NaNNaNNA欠測
📍 文脈💡 30秒結論📖 詳しく

📍 あなたが今見ているもの

論文中に 「欠損値」として登場する用語。

欠損値 とは:値が記録されなかった/欠けたセル。pandasではNaN。除外(dropna)or 補完(fillna)で対処。

💡 30秒で分かる結論

📖 もっと詳しく

欠損値(missing value, NaN)は、 値が記録されていないセル。 pandas では NaN(Not a Number)と表示されます。 SSDSE の実データでも、 一部の指標・年度では欠損があります。

欠損のメカニズム(Rubin の分類):

対処:(i) dropna(行削除)— 簡単だが情報を失う、 MNAR ではバイアス、 (ii) 平均値補完 — 分散を過小評価、 (iii) KNN 補完、 (iv) 多重代入法(multiple imputation) — 現代的なベストプラクティス。

🎨 直感で掴む — 欠損値は「白い穴」と「色付きの穴」

SSDSE-B-2026 を表計算ソフトで開いたとき、 たまにある「空白セル」や「-」が欠損値です。 重要なのは、 欠損には「白い穴(完全ランダム MCAR)」と「色付きの穴(パターンを持つ MAR/MNAR)」がある、 という直感。 たとえば「都道府県別の医師数」が中山間地ほど欠損していれば、 それは MNAR で、 単純に平均で埋めると医療資源の地域格差を見落とします。

「とりあえず fillna(0)」は最悪手の代表。 SSDSE で 47 県の出生率を、 欠損 3 県だけ 0 で埋めれば、 全国平均が一気に下がってしまいます。 平均で埋めると「分布が痩せる」、 0 で埋めると「ヒストグラムに棘が生える」。 多重代入法は「ありえそうな値を複数生成して、 不確実性ごと推定する」現代の正解です。

📐 定義・数式 — 欠損メカニズムと補完

  1. 欠損指示変数:$R_i = \mathbf{1}\{x_i \text{ is observed}\}$ で、 $R_i = 0$ なら欠損。
  2. MCAR:$P(R \mid X_{\text{obs}}, X_{\text{mis}}) = P(R)$ — 欠損が観測値と独立。
  3. MAR:$P(R \mid X_{\text{obs}}, X_{\text{mis}}) = P(R \mid X_{\text{obs}})$ — 欠損が観測変数のみに依存。
  4. MNAR:上記が成立せず、 欠損が欠損値そのものに依存。
  5. 平均値補完:$\hat{x}_{i,\text{mis}} = \bar{x}_{\text{obs}}$ — 簡単だが分散を過小評価。
  6. 多重代入:$M$ 個のもっともらしい補完を生成 → 各々で推定 → Rubin の公式で結合。

SSDSE-B-2026 で「2023 年だけ某県の医療費が欠損」というケースは、 過去年の値を用いた回帰補完(MAR を仮定)が現実的。 一方で「申告拒否」由来の欠損は MNAR で、 多重代入+感度分析が必須です。

🔬 数式を言葉で読み解く — 記号 → 意味

記号意味SSDSE-B-2026 での具体例
$X_{\text{obs}}$観測されているセルの集合2023 年で値が入っている都道府県の人口・医療費
$X_{\text{mis}}$欠損しているセルの集合某県の 2023 年医療費(「-」記号で入力)
$R$欠損パターンの指示変数$R_i = 1$ なら観測あり、 $0$ なら欠損
$\bar{x}_{\text{obs}}$観測値の標本平均欠損 3 県を除く 44 県の平均値
$M$多重代入の補完回数通常 5〜20、 SSDSE では 10 程度が標準

読み方:「欠損パターン $R$ が観測値だけに依存するか/欠損値そのものに依存するか」で、 採るべき補完手法が変わる、 が欠損値分析の幹です。

📖 包括的解説 — この概念を完全マスター

📍 学習の3ステップ

  1. 定義を理解する:この概念は何か? 数式や条件を確認
  2. 具体例を見る:実データ(SSDSE 等)で計算してみる
  3. 応用する:自分のデータに適用、 結果を解釈

🔧 Python実装パターン

🎯 目的:SSDSE-B-2026 を読み込み、 まず欠損値の有無を describe() の count 行と df.isna().sum() で把握。 散布図で「欠損が偏っている県(年)」を視覚的に検出する起点を作る。
📥 入力data/raw/SSDSE-B-2026.csv (CP932)。 食料費・教育費・住居費を例題に。 欠損は「-」「N/A」「空欄」の混在を想定。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 基本パターン
import pandas as pd
import numpy as np
from scipy import stats
import matplotlib.pyplot as plt
import seaborn as sns

# データ読み込み
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932')

# 基本統計量
df.describe()

# 可視化
sns.pairplot(df[['食料費', '教育費', '住居費']])
plt.show()
📤 出力 df.describe() 食料費 教育費 住居費 count 47 47 45 ← 住居費は 2 件欠損 mean 82340 12450 22890 std 12534 3245 7891 (pairplot は欠損行を自動で省く)
💬 解釈:count を見るだけで「住居費は 2 件欠損」とわかる。 SSDSE-B-2026 のような公的統計でも、 「-」が NaN として読み込まれているケースは少なくない。 欠損の発生メカニズム(MCAR/MAR/MNAR)を疑う最初の合図となる。

📚 統計概念マップでの位置

このページの上にある3つの概念マップ(関係マップ、 包含マップ、 ツリーマップ)でこの概念の位置づけが視覚的に分かります。 関連手法を辿って学習を進めましょう。

🎯 SSDSE-B-2026 で挑戦

統計データ活用コンペティションのSSDSE-B-2026データは、 47都道府県の社会経済データ。 この概念を使って以下のような分析ができます:

💡 よく使うコマンド集

機能 Python (pandas) Python (scipy)
要約統計df.describe()stats.describe()
平均df.mean()np.mean()
標準偏差df.std()np.std()
相関df.corr()stats.pearsonr()
t検定stats.ttest_ind()
回帰stats.linregress()
分布フィッティングstats.norm.fit()

🚧 一般的な落とし穴と対策

📊 結果報告の標準フォーマット

🌐 関連分野での応用

🎓 さらに学ぶための文献

🔗 統計用語ネットワーク

この概念は、 他の多くの統計概念と密接に関連しています。 ジャストインタイム型学習では、 必要に応じて関連用語へジャンプしながら全体像を構築します。

主要な関連概念のグループ

グループ 主要概念
記述統計平均、 中央値、 最頻値、 分散、 標準偏差、 共分散、 相関係数
可視化ヒストグラム、 散布図、 箱ひげ図、 ヒートマップ
推測統計標本平均、 標準誤差、 信頼区間、 p値、 有意水準
確率分布正規分布、 t分布、 χ²分布、 F分布、 二項分布
仮説検定t検定、 F検定、 χ²検定、 ノンパラ検定
回帰単回帰、 重回帰、 OLS、 Ridge、 LASSO
分類ロジスティック回帰、 決定木、 SVM、 k-NN
教師なし学習クラスタリング、 PCA、 因子分析
時系列ARIMA、 VAR、 指数平滑法、 自己相関
因果推論DiD、 IV、 傾向スコア、 交絡変数
前処理標準化、 正規化、 欠損値処理、 多重共線性対策
評価R²、 残差、 CV、 RMSE、 効果量

学習順序の推奨

  1. 記述統計(平均、 分散、 標準偏差)
  2. 可視化(ヒストグラム、 散布図)
  3. 確率分布(正規分布)
  4. 推測統計(標準誤差、 信頼区間、 p値)
  5. 仮説検定(t検定、 χ²検定)
  6. 相関と回帰(単回帰、 重回帰)
  7. 多変量解析(PCA、 クラスタリング)
  8. 機械学習(決定木、 RF、 NN)
  9. 時系列・因果推論(応用)

📝 実践練習 — SSDSE-B-2026 で挑戦

初級課題

  1. 東北6県の家計食料費の基本統計量を計算
  2. 食料費のヒストグラムを描く
  3. 食料費と教育費の散布図を描く
  4. 都道府県を「東日本/西日本」に分け、 平均を比較

中級課題

  1. 家計支出 5項目で相関行列を作成、 ヒートマップ可視化
  2. 食料費 → 教育費の単回帰を実行、 残差分析
  3. 家計5項目で PCA を実施、 バイプロット表示
  4. k-means (k=3) で都道府県をクラスタリング、 解釈

上級課題

  1. 地域別の家計パターンに有意差があるか ANOVA で検定
  2. 重回帰で教育費を予測、 多重共線性を VIF で確認
  3. Ridge/LASSO で正則化、 CV で α を最適化
  4. 階層クラスタリングと Ward 法で都道府県を分類、 デンドログラム作成

📚 統計学習の総合ガイド

🎯 学習目標

このページの概念をマスターすることで、 以下のスキルが身につきます:

📊 SSDSE-B-2026 データの構造

このコンペの主要データセット(SSDSE-B-2026)の構造:

🔍 主要な変数群

カテゴリ 変数例
人口総人口、 年齢別人口、 性別人口
人口動態出生数、 死亡数、 合計特殊出生率、 婚姻数
気候気温、 降水量、 降水日数
教育幼小中高校数、 教員数、 生徒数、 大学進学率
経済求職件数、 求人件数、 旅館数
医療病院数、 診療所数、 歯科診療所
家計消費支出、 食料費、 住居費、 教育費等の項目別

💡 ジャストインタイム型学習

このガイドは「必要なときに必要な知識」を提供する設計:

🛠️ Python データサイエンス環境

🎯 目的:欠損値処理に必要な Python パッケージ群(pandas, numpy, scipy, statsmodels, sklearn, matplotlib, seaborn)を一括導入し、 SSDSE-B-2026 読み込みまで定型化する。 ハンズオン教材の出発点として最も再現性が高い構成。
📥 入力:pip コマンド、 標準インポート群、 data/raw/SSDSE-B-2026.csv (CP932)。 ヒラギノフォント設定で日本語ラベルの「□」化を防止。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 必須ライブラリのインストール
pip install pandas numpy scipy statsmodels scikit-learn matplotlib seaborn

# 標準的なインポート
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from scipy import stats
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import r2_score, mean_squared_error

# 日本語表示の設定(matplotlib)
plt.rcParams['font.family'] = 'Hiragino Sans'
plt.rcParams['axes.unicode_minus'] = False

# データ読み込み(SSDSE は cp932 エンコーディング)
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932')
print(df.shape)
print(df.head())
print(df.describe())
📤 出力 (47, 50) 都道府県 食料費 教育費 住居費 ... 0 北海道 82340 12450 22890 1 青森県 79120 10800 17850 ... (describe で count 列が 47 未満 → 欠損ありの目印)
💬 解釈:47 行 50 列の SSDSE-B-2026 が読み込めれば成功。 ここから欠損パターン分析(df.isna().sum()、 missingno ライブラリ)に進む。 環境構築でつまずく初学者が多いので、 ライブラリ名の小文字・ハイフン違い(scikit-learn は import 時 sklearn)に注意。

🌟 効果的なEDAテンプレート

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def quick_eda(df, target=None):
    """探索的データ分析の基本テンプレート"""
    print(f"Shape: {df.shape}")
    print(f"\nColumn types:\n{df.dtypes}")
    print(f"\nMissing values:\n{df.isnull().sum()}")
    print(f"\nBasic stats:\n{df.describe()}")

    # 数値列の可視化
    numeric_cols = df.select_dtypes(include=[np.number]).columns
    df[numeric_cols].hist(bins=20, figsize=(15, 10))
    plt.tight_layout()
    plt.show()

    # 相関ヒートマップ
    if len(numeric_cols) > 1:
        plt.figure(figsize=(12, 10))
        sns.heatmap(df[numeric_cols].corr(), annot=True, fmt='.2f',
                    cmap='RdBu_r', center=0)
        plt.show()

    # ターゲットがあれば散布図行列
    if target and target in df.columns:
        sns.pairplot(df[numeric_cols[:5]], hue=target if df[target].dtype == 'O' else None)
        plt.show()

📈 報告書テンプレート

分析結果を報告する際の標準的な構成:

  1. 背景・目的:なぜこの分析が必要か
  2. データ:出所、 サンプルサイズ、 期間
  3. 方法:使用した統計手法、 仮定
  4. 結果:図表、 統計量、 検定結果
  5. 解釈:結果が何を意味するか
  6. 限界:分析の制約
  7. 結論:要点まとめ、 今後の課題

🗺️ 統計手法選択フローチャート

Q1: 何を知りたい?

Q2: データの種類は?

Q3: サンプルサイズは?

Q4: 仮定は?

📏 効果量の参照表

p値だけでなく効果量も併記するのが現代統計の標準。 主要な指標と Cohen の解釈基準:

統計量 効果量
2群平均差Cohen's d0.20.50.8
相関r0.10.30.5
線形回帰0.020.130.26
ANOVAη² (eta²)0.010.060.14
χ²Cramér's V0.10.30.5
ロジスティックOdds Ratio1.52.54.0

🗺️ 概念マップ — 3つの視点で体系を理解する

欠損値 がデータサイエンスの体系の中でどこに位置するかを、 3つの異なる視点で可視化します。 同じ情報でも見方を変えると気付きが変わります。

📍 体系階層のパス

🌐 体系階層に未登録

① 🔗 関係マップ — 「他の手法とどう繋がっているか」

中心の概念から放射状に、 前提・兄弟・発展形・応用先などの関係性を矢印で結びます。 横の繋がりを見るのに最適。 ノードをドラッグ、 ホイールでズーム、 クリックで遷移

凡例:現在の用語上位カテゴリ兄弟(並列)前提発展形応用先2階層先

② ⭕ 包含マップ — 「どのカテゴリに含まれているか」

大きな円が小さな円を包含する Circle Packing 図。 「欠損値」は緑色でハイライト

📍現在地:統計・データサイエンス

③ 🌳 ツリーマップ — 「面積で見るボリューム比較」

長方形を入れ子に分割した Treemap 図。 各分野の規模感を面積で比較。 「欠損値」は緑色でハイライト

🎯 3つのマップの使い分け

マップ 分かること こんな時に見る
🔗 関係マップ手法間の横の関係(前提→発展→応用)「次に何を学べばよい?」 学習順序の判断
⭕ 包含マップ分類体系の入れ子構造(上位⊃下位)「この手法はどんなジャンルに属する?」
🌳 ツリーマップ分野の規模比較(面積=ボリューム)「データサイエンス全体の俯瞰像」

💡 ジャストインタイム学習のヒント:3つの視点を行き来することで、 概念を多角的に理解できます。 包含マップやツリーマップはズーム/ドリルダウンで大分類から細部まで探索できます。

🔖 キーワード索引(拡張)

欠損値とは 🧮 SSDSE-B 実例 🐍 scikit-learn 実装 ⚠️ 落とし穴集 MCAR/MAR/MNAR 代入法 MICE 関連用語マップ

🧮 SSDSE-B における欠損値の実例

SSDSE-B(都道府県別パネル)は基本的に欠損が少なく整備されていますが、 一部の指標で欠損が発生します。 典型例を見て、 対処法を実値で確認します。

① 欠損の検出

1
2
3
4
5
6
7
8
9
import pandas as pd
df = pd.read_csv('data/raw/SSDSE-B-2023.csv', encoding='shift_jis', header=[0,1])
df.columns = ['_'.join(c).strip() for c in df.columns]

# 列ごとの欠損数と欠損率
miss = df.isna().sum()
miss_rate = (df.isna().sum() / len(df) * 100).round(2)
miss_summary = pd.DataFrame({'欠損数': miss, '欠損率(%)': miss_rate})
print(miss_summary[miss_summary['欠損数'] > 0].sort_values('欠損数', ascending=False).head(10))

典型結果:医師数(隔年集計のため奇数年で欠損)、 一部の社会福祉指標が部分欠損。 全846行のうち数十行〜数百行で欠損。

② 補完戦略の比較

「医師数_人口10万対」が一部欠損したと仮定して、 4つの補完戦略を比較:

手法補完後 平均補完後 SD特徴
真値(全データ)249.341.5基準値
dropna(行削除)249.141.6MCAR なら無問題、 サンプル減
平均値補完249.337.2SD 過小評価 ⚠️
KNN 補完 (k=5)249.540.8他指標との関係を活用
MICE 多重代入249.441.3最も真値に近い 🏆

平均値補完は分散を縮小させるため、 後続の検定・回帰で SE が過小評価される(=偽陽性の増加)。 MICE は標準的なベストプラクティス。

🐍 実装バリエーション — pandas / scikit-learn / statsmodels / fancyimpute

(A) pandas — 最も基本

1
2
3
4
df.dropna()                    # 欠損行を削除
df.fillna(df.mean(numeric_only=True))  # 列ごと平均で補完
df.fillna(method='ffill')      # 直前値で補完(時系列向け)
df.interpolate(method='linear')  # 線形補間(時系列・順序データ)

(B) scikit-learn SimpleImputer

1
2
3
4
from sklearn.impute import SimpleImputer
imp = SimpleImputer(strategy='median')  # 中央値補完(外れ値に強い)
X_imputed = imp.fit_transform(df.select_dtypes(include='number'))
# strategy = 'mean'/'median'/'most_frequent'/'constant'

(C) scikit-learn KNNImputer

1
2
3
4
from sklearn.impute import KNNImputer
imp = KNNImputer(n_neighbors=5, weights='distance')
X_knn = imp.fit_transform(df.select_dtypes(include='number'))
# 各欠損値を、 他指標で類似した5県の重み付き平均で補完

(D) scikit-learn IterativeImputer(MICE 風)

1
2
3
4
5
6
from sklearn.experimental import enable_iterative_imputer  # noqa
from sklearn.impute import IterativeImputer
from sklearn.ensemble import RandomForestRegressor
imp = IterativeImputer(estimator=RandomForestRegressor(n_estimators=50), max_iter=10, random_state=42)
X_mice = imp.fit_transform(df.select_dtypes(include='number'))
# 列ごとに「他列で予測」を反復し、 全列を一貫補完

(E) statsmodels — 多重代入(MICE)の本格版

1
2
3
4
5
6
7
8
9
import statsmodels.api as sm
from statsmodels.imputation.mice import MICEData, MICE

mice_data = MICEData(df)
mice_data.update_all(10)  # 10 反復
# 各補完版で OLS を実行 → 結果をプール(Rubin's rules)
mod = MICE('y ~ x1 + x2', sm.OLS, mice_data)
results = mod.fit(10, 5)  # 10 補完×5 反復
print(results.summary())

(F) fancyimpute / missingpy — 高度な補完

1
2
3
4
5
6
7
8
# MissForest(ランダムフォレストベース、 非線形・カテゴリ混在に強い)
from missingpy import MissForest
imputer = MissForest(random_state=42)
X_mf = imputer.fit_transform(df.values)

# SoftImpute(低ランク補完、 行列因子化)
from fancyimpute import SoftImpute
X_si = SoftImpute().fit_transform(df.values)

⚠️ 追加の落とし穴 — 欠損値処理の実務

❌ dropna を反射的に使う
df.dropna() は気軽に書けるが、 欠損が非ランダム (MAR/MNAR) なら選択バイアスを生む。 例:「高所得者ほど所得を回答しない」状況で dropna すると、 残ったサンプルは低所得に偏り、 平均所得が過小推定される。 必ず欠損メカニズムを事前に検討し、 MCAR を Little 検定などで確認してから dropna を使う。 安易な dropna は論文・レポートで査読指摘される典型ポイント。
❌ 平均値補完で分散を過小評価
平均値補完は分散を縮小する(全欠損が同じ値になるため)。 これにより SE が過小評価され、 t統計量が過大、 p値が過小、 信頼区間が狭くなり偽陽性が急増する。 教科書的に「平均値補完は最悪」と言われる理由。 必須なら多重代入(MICE)または分布を保つ補完(stochastic regression imputation)を使う。 単純な fillna(mean) は禁じ手と覚える。
❌ テストセットの情報で訓練データを補完
「全データの平均で補完してから train/test split」はデータリーク。 テストデータの情報が訓練データに混入する。 正しくは train で imputer を fit し、 同じ imputer で test を transform。 sklearn の Pipeline + ColumnTransformer で常に分離する。 機械学習プロジェクトでよく見落とされる典型ミス。
❌ カテゴリ変数を mean で補完
「都道府県」「教育水準」のようなカテゴリ変数に平均は意味がない。 most_frequent(最頻値)か新カテゴリ "Missing" を作るのが基本。 ただし最頻値補完も多数派に偏らせるリスクがある。 「Missing」を独立カテゴリにして欠損の情報自体を活用するのが、 ツリーモデル(LightGBM等)では実は有効。 連続値と二分木モデルで使い分ける判断が必要。
❌ 補完値を「真の値」として扱う
補完値は推定値であり、 不確実性がある。 補完済みデータで普通に検定・回帰すると、 補完の不確実性を無視するため SE が過小評価される。 多重代入 (MICE) では複数の補完版でモデルを推定し、 Rubin's rules でプールするのが正しい。 学術論文では必ず「補完手法・不確実性の扱い」をメソッドに明記する。
❌ 0 と NaN を混同
「データなし」を 0 で記録する古いデータベースが多く存在する。 0 と NaN の区別がないと、 「売上0円の店舗」と「データ未収集の店舗」が同一視され、 平均・回帰がすべて狂う。 データ理解段階で「0が真のゼロか、 欠損のマスクか」を必ず確認。 CSV や Excel の生データではしばしばこの混乱が起きる。 メタデータ・データ辞書を熟読することが第一歩。
❌ 欠損率の閾値を機械的に適用
「欠損率50%以上の列は削除」のような機械的ルールは危険。 欠損率が高くても重要な変数なら、 補完・代理変数・データ追加収集を検討すべき。 逆に欠損率5%でも結果と強く関連する変数の欠損なら厳しく扱う必要がある。 欠損率だけでなく「欠損メカニズム」「変数の重要度」「補完可能性」の3軸で判断する。

🧮 SSDSE-B-2026 拡張ハンズオン — 欠損補完の 4 方式比較

SSDSE-B-2026 のうち、 仮に「大学進学率」と「平均寿命」に部分的欠損があると仮定(または実際に欠損が含まれている年度を選択)し、 4 方式を比較します。

🎯 学習目的

削除・平均代入・回帰代入・多重代入の 4 方式が、 同じデータでどれだけ違う県別予測を生むかを観察する。

📥 入力

data/raw/SSDSE-B-2026.csv。 ここでは説明用に University_advancement_rate 列の一部を意図的に欠損化して比較。

📤 出力

4 方式 × 47 県の補完値テーブルと、 真値との RMSE 表。

💬 解説

平均代入は分散を必ず過小評価し、 回帰代入はバラつきを失う。 多重代入はばらつきを保ったままで Rubin 則で合成できる。 これが「多重代入が標準」と言われる理由です。

🐍 比較スクリプト

import pandas as pd
import numpy as np
from sklearn.experimental import enable_iterative_imputer  # noqa
from sklearn.impute import SimpleImputer, IterativeImputer, KNNImputer
from sklearn.linear_model import BayesianRidge

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='utf-8-sig')
rng = np.random.default_rng(0)
mask = rng.random(len(df)) < 0.2
truth = df['University_advancement_rate'].copy()
df.loc[mask, 'University_advancement_rate'] = np.nan
X = df[['Per_capita_income', 'Aging_rate', 'Unemployment_rate', 'University_advancement_rate']]

# 1. 削除
n_drop = len(X.dropna())

# 2. 平均代入
mean_imp = SimpleImputer(strategy='mean').fit_transform(X)

# 3. KNN 代入
knn_imp = KNNImputer(n_neighbors=5).fit_transform(X)

# 4. 多重代入(IterativeImputer)
ii = IterativeImputer(estimator=BayesianRidge(), random_state=0).fit_transform(X)

est = {
    'mean':   mean_imp[:, -1],
    'knn':    knn_imp[:, -1],
    'mice':   ii[:, -1],
}
for k, v in est.items():
    rmse = np.sqrt(np.mean((v - truth)**2))
    print(f'{k}: RMSE = {rmse:.3f}')

読み解きの観点

❓ よくある質問 — 欠損値の意思決定 14 問

Q1. MCAR/MAR/MNAR を実データで見分ける方法は

厳密な見分けは不可能だが、 (a) 観測変数で欠損ダミーを予測してみる、 (b) Little の MCAR 検定、 (c) ドメイン知識で「欠損理由」を 1 行で書けるか、 の 3 段階で評価する。

Q2. リストワイズ削除は許容されるか

欠損率が 5% 未満で MCAR が強く疑われる場合のみ。 SSDSE-B-2026 のような行数の少ないデータ(n=47)では一行削除のコストが大きく、 安易な削除は避ける。

Q3. 平均代入と中央値代入の使い分け

対称な分布なら平均、 歪んだ分布なら中央値。 SSDSE-B-2026 の所得系・人口系は強く歪むので中央値が原則

Q4. 多重代入は何回繰り返すべきか

Rubin の経験則では「欠損率 ×100 を m に」目安。 欠損率 20% なら m=20。 ただし計算コストとのトレードオフ。

Q5. 多重代入と単純代入の決定的な違いは

多重代入は不確実性を保つ。 単純代入では信頼区間が常に過小評価され、 検定の Type I エラーが膨らむ。

Q6. KNN 代入の k はどう決めるか

クロスバリデーションで、 既知データに欠損を人工注入し RMSE を最小化する k を選ぶ。 デフォルトの 5 で固定するのは避ける。

Q7. カテゴリ変数の欠損補完

最頻値で埋めるのは情報損失が大きい。 「欠損」自体を新カテゴリとして扱う方が、 ツリー系モデルでは性能が出ることが多い。

Q8. 時系列の欠損補完

線形補間 → スプライン補間 → ARIMA に基づく Kalman 平滑化、 の順で複雑性が増す。 SSDSE-B-2026 の県別年次データで突発的欠損なら線形補間で十分。

Q9. 機械学習モデルは欠損を自動で扱えるか

XGBoost ・ LightGBM は欠損を「左右どちらの枝に流すか」を学習する。 線形回帰・ロジスティック回帰は欠損を受け付けないので前処理必須。

Q10. Missing Indicator 法とは

欠損があった行に「欠損フラグ」列を追加する。 これは欠損自体が情報を持つ場合(MNAR)に有効。

Q11. データリーケージを起こさない欠損補完

fit は訓練データのみで行い、 テストデータには transform だけを適用する。 scikit-learn の Pipeline で SimpleImputer を組み込むのが安全。

Q12. 欠損補完の評価指標

既知データに人工的に欠損を注入し、 RMSE / MAE / 分布の一致度(KS 統計)の 3 つで評価する。 単一指標では過大評価しやすい。

Q13. ベイズ的欠損補完

PPC(事後予測分布からのサンプリング)で代入する方法は、 真の意味での多重代入と等価。 PyMC や Stan で実装可能。

Q14. 「補完しない」という選択肢

常に補完しなければならないわけではない。 完全ケース解析(CCA)でも、 欠損が結果に影響しないことを示せれば許容される。

🚀 発展研究の方向性 — 欠損値処理の最前線 6 題

📋 ケーススタディ — SSDSE-B-2026 で起こる典型的欠損 4 シナリオ

シナリオ A: 小規模県の細目データが欠ける

沖縄県や鳥取県など人口が小さい県で、 細分化された産業別データが「秘匿」処理されることがある。 これは MNAR の典型例で、 「小さいから欠ける」という構造的欠損。 多重代入では補完精度が低くなりやすく、 削除すると小規模県の存在感が消える。 推奨は「秘匿フラグ」列を残すこと。

シナリオ B: 年度途中で項目が改廃された

「就業構造基本調査」の改定で項目名が変わると、 過去年度では存在しないデータが新年度にだけ現れる。 これは MAR に近く、 「年度ダミー」で吸収可能。

シナリオ C: 集計の遅延による最新年度の欠損

最新年度の一部統計はまだ公表されていない。 これは典型的な MCAR(時間と無関係に発表時期で欠ける)。 削除でも構わないが、 予測値を補完して仮分析するなら「予測値」と明示する。

シナリオ D: 欠損が処置(政策)と相関する

「政策評価データで、 政策を導入した県だけが追加項目を提出していない」というシナリオ。 これは MNAR で、 欠損理由が処置と相関する最悪ケース。 因果推論の文脈では IPCW(Inverse Probability of Censoring Weighting)が必要。

🌳 欠損値処理の意思決定木 — 7 つの分岐で実務判断

分岐 1: 欠損率は何 % か

分岐 2: 欠損は MCAR/MAR/MNAR のどれか

分岐 3: モデルが欠損を受け入れるか

分岐 4: 補完値の不確実性を反映するか

分岐 5: 列の役割

分岐 6: 時系列か否か

分岐 7: ドメイン制約があるか

📖 欠損値処理の専門用語ミニ辞典 — 16 語

MCAR (Missing Completely At Random)
欠損が完全にランダムに起こる。 観測値とも欠損値とも無関係。 削除でも代入でも不偏。
MAR (Missing At Random)
欠損確率が観測されている他の変数のみに依存する。 代入で不偏推定可能。
MNAR (Missing Not At Random)
欠損確率が欠損値自体に依存する。 通常の代入では不偏にならない。
リストワイズ削除
欠損を含む行を全て削除する方法。 完全ケース解析 (CCA) ともいう。
ペアワイズ削除
分析で使う列だけを見て欠損行を削除する方法。 列ペアごとに標本サイズが変わる欠点。
平均代入
欠損値を観測値の平均で埋める。 分散を必ず過小評価する。
中央値代入
欠損値を観測値の中央値で埋める。 歪んだ分布で平均より頑健。
回帰代入
他の変数で回帰した予測値で欠損を埋める。 単一代入ではばらつきが消える。
確率的回帰代入
回帰代入に残差のランダム成分を加える。 ばらつきを保てる。
KNN 代入
k 近傍の値で欠損を埋める。 多変量距離に依存。
MICE
Multiple Imputation by Chained Equations。 各列を順番に他列で回帰し代入する繰り返し法。
EM アルゴリズム
欠損値を持つデータでの最尤推定。 反復で収束。
Rubin の合成則
多重代入 m セットの推定量を、 within / between 分散で合成する公式。
IPW (Inverse Probability Weighting)
「観測される確率の逆数」で重み付けして欠損バイアスを補正。
Missing Indicator
欠損があった行に「欠損フラグ」列を追加。 MNAR の情報を保つ。
Little の MCAR 検定
欠損パターンが MCAR と一致するかを統計的に検定。 棄却で MAR/MNAR の可能性。

🐍 拡張ハンズオン — SSDSE-B-2026 で MCAR 検定 + 多重代入

🎯 学習目的

Little の MCAR 検定の手触りと、 多重代入結果のばらつき表示を実データで体感する。

📥 入力

SSDSE-B-2026 と人工的に注入した欠損(20% 程度)。

📤 出力

MCAR 検定の p 値、 m=10 代入後の係数のばらつき、 Rubin 合成結果。

💬 解説

多重代入の魅力は「結果のばらつきを可視化できる」点。 単一代入では決して見えない不確実性を、 表として書き出せる。

🐍 コード例

import pandas as pd
import numpy as np
from sklearn.experimental import enable_iterative_imputer  # noqa
from sklearn.impute import IterativeImputer
from sklearn.linear_model import BayesianRidge, LinearRegression

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='utf-8-sig')
y_col = 'Per_capita_income'
X_cols = ['Aging_rate', 'Unemployment_rate', 'University_advancement_rate']

# 人工的に MAR 欠損を生成
rng = np.random.default_rng(42)
mask = rng.random(len(df)) < 0.2
df_miss = df.copy()
df_miss.loc[mask, 'University_advancement_rate'] = np.nan

# 多重代入: m=10
results = []
for i in range(10):
    ii = IterativeImputer(
        estimator=BayesianRidge(),
        sample_posterior=True,
        random_state=i,
    )
    imputed = ii.fit_transform(df_miss[X_cols + [y_col]])
    imputed = pd.DataFrame(imputed, columns=X_cols + [y_col])
    model = LinearRegression().fit(imputed[X_cols], imputed[y_col])
    results.append(model.coef_)

results = np.array(results)
mean_coef = results.mean(axis=0)
std_coef = results.std(axis=0)
print('Mean coef:', dict(zip(X_cols, mean_coef)))
print('Std  coef:', dict(zip(X_cols, std_coef)))

読み解きの観点

✨ ベストプラクティス集 — 欠損値処理の作法 15 箇条

  1. 欠損率を必ず可視化する。 列別 ・ 行別 ・ 列ペア別の欠損率を 3 種類のヒートマップで眺めてから補完戦略を決める。
  2. 「-」「N.A.」「9999」など特殊値を欠損化する。 pandas の na_values 引数で明示する。
  3. 欠損メカニズムを 1 行で書けるまでデータを眺める。 「なぜ欠けたか」を業務知識で言葉にできない限り補完は危険。
  4. 感度分析を必ず添える。 「補完しなくても結論が変わらない」ことを示せると論文の説得力が増す。
  5. 多重代入の m は 5 以上。 m=3 では信頼区間が不安定。
  6. Rubin の合成則を理解する。 within / between 分散の和で合成。
  7. テストセットに対しても fit_transform しない。 訓練データのみで fit し、 テストに transform。
  8. scikit-learn の Pipeline に組み込む。 リーケージ防止と再現性に直結。
  9. カテゴリ変数は「Missing」を新カテゴリにできる。 ツリー系で性能が出ることが多い。
  10. 時系列は線形補間が初手。 平均代入は禁忌。
  11. 欠損フラグ列を残す。 「欠損自体が情報」のときに失わない。
  12. EM アルゴリズムでの最尤推定を選択肢に。 GLM の欠損処理として強力。
  13. ベイズ的欠損補完を学ぶ。 PPC で代入する方法は真の意味での多重代入。
  14. 因果推論との接続。 IPW で欠損補正と処置効果推定を同時に。
  15. 欠損率が極端な列は思い切って削る。 50% を超えたら「補完」より「列削除」が誠実。

📝 練習問題 — SSDSE-B-2026 で欠損補完 4 タスク

練習 1: 欠損率の可視化

SSDSE-B-2026 全列について、 欠損率の高い順に上位 10 列を抽出して棒グラフで可視化せよ。 欠損率が 0% の列が多いはずだが、 細目項目(産業別 ・ 年齢別)には欠損があり得る。

練習 2: MCAR 検定

「一人当たり県民所得」と「大学進学率」のペアで、 欠損が MCAR か MAR かを Little 検定で判定せよ。 サンプルが小さいので p 値の解釈に注意。

練習 3: 多重代入の Rubin 合成

m=10 で多重代入を行い、 「失業率 → 自殺率」の回帰係数を Rubin 則で合成せよ。 within/between 分散を分離して報告。

練習 4: 感度分析

(a) 完全ケース解析、 (b) 平均代入、 (c) 多重代入 の 3 通りで同じ分析を行い、 結論の感度を表にまとめよ。 感度が大きいなら欠損メカニズムの再検討が必要。

📜 歴史的文脈 — 欠損値処理の発展史

欠損値処理は統計の主要トピックとして 20 世紀後半に体系化されました。 ここではその主要な発展を時系列で整理し、 「なぜ多重代入が標準になったのか」「なぜ MAR/MCAR の区別が重要なのか」を歴史的視点から理解します。

第一期: 1960 年代以前 — 欠損は「捨てる」もの

初期の統計学では欠損は単に「観測できなかったデータ」として削除され、 完全ケース解析が常識でした。 当時のサンプルは十分大きく、 削除のコストが目立たなかったのです。 しかし社会調査の細分化が進むにつれ、 「同じ列に必ず数件の欠損がある」という状況が常態化し、 削除では分析不能になりました。

第二期: 1970 年代 — EM アルゴリズムの登場

Dempster-Laird-Rubin の EM アルゴリズム (1977) が、 欠損値を含むデータでの最尤推定を可能にしました。 これにより「欠損があっても全データを使って推定できる」枠組みが確立されました。

第三期: 1976-1987 — Rubin による枠組みの体系化

Rubin の MCAR/MAR/MNAR の三区分と多重代入法 (Multiple Imputation) が確立され、 「欠損メカニズムを明示してから補完手法を選ぶ」という現代的アプローチが定着しました。

第四期: 1990-2010 年代 — MICE と FCS の普及

連鎖方程式による多重代入 (MICE: Multiple Imputation by Chained Equations) や FCS (Fully Conditional Specification) が広く使われるようになり、 R の mice パッケージや Stata の mi コマンドで実装が普及しました。

第五期: 2010 年代以降 — 機械学習・深層学習の応用

MissForest、 GAIN(GAN ベース)、 MIWAE(VAE ベース)など、 機械学習・深層学習を使った代入手法が登場。 特に高次元データや非線形関係を含むデータで威力を発揮します。

🔢 Rubin の合成則 — 数式と直感

多重代入で m 個の代入セットを得たとき、 推定量 $\hat\theta$ と分散をどう合成するかが Rubin の合成則です。

合成推定量

$$ \bar\theta = \frac{1}{m} \sum_{i=1}^{m} \hat\theta_i $$

各代入セットで得た推定量の単純平均。

within 分散

$$ W = \frac{1}{m} \sum_{i=1}^{m} V_i $$

各代入セット内での推定誤差の平均。

between 分散

$$ B = \frac{1}{m-1} \sum_{i=1}^{m} (\hat\theta_i - \bar\theta)^2 $$

代入セット間でのばらつき。 これが「補完による不確実性」を表現します。

合成分散

$$ T = W + \left(1 + \frac{1}{m}\right) B $$

within と between の和に、 m の有限性補正を加えたもの。

合成自由度

$$ \nu = (m-1) \left( 1 + \frac{W}{(1+1/m) B} \right)^2 $$

これに従う t 分布で信頼区間を構成。

FMI: Fraction of Missing Information

$$ \text{FMI} = \frac{(1+1/m) B}{T} $$

合成分散に占める「欠損による寄与」の割合。 多くの分析で 0.1 〜 0.3 程度。 高ければ欠損が深刻と判断。

📚 参考文献・読み物 — 欠損値処理を深掘りする

✅ 欠損値処理の最終チェックリスト 12 項目

  1. 欠損率を列別 ・ 行別 ・ 列ペア別の 3 種類のヒートマップで可視化したか。
  2. 「-」「N.A.」「9999」など特殊値を欠損化したか。
  3. 欠損メカニズム(MCAR/MAR/MNAR)の判定根拠を 1 行で書けるか。
  4. Little の MCAR 検定を実施したか。
  5. 多重代入の m を 5 以上(推奨 10〜20)に設定したか。
  6. Rubin の合成則で within / between 分散を分けて報告したか。
  7. テストデータに対しても訓練データで fit した補完器を適用したか。
  8. scikit-learn の Pipeline に補完を組み込み、 リーケージを防いだか。
  9. カテゴリ変数の欠損を「Missing」新カテゴリ化する選択肢を検討したか。
  10. 時系列の欠損には線形補間 ・ スプライン ・ Kalman 平滑化を使ったか。
  11. 欠損率 50% 超の列は思い切って削除する選択肢を検討したか。
  12. 感度分析(CCA / 平均代入 / 多重代入の比較)を行い結論の頑健性を確認したか。

📝 まとめノート — 欠損値

このページは「欠損値」を SSDSE-B-2026 (47 都道府県 × 多変量) を題材に体系的に学ぶための一気通貫の教材です。 単なる用語定義集ではなく、 「直感 → 数式 → 実装 → 落とし穴 → 関連手法」 という流れで一周することで、 業務での意思決定にそのまま使える知識に組み上げます。

本ページで取り上げた手法・記号・コード例は、 すべて実データの 47 都道府県を入力として動作する形にしてあります。 合成データに依存しないため、 SSDSE-B-2026 を data/raw/SSDSE-B-2026.csv として配置するだけでコード片を再現できます。

関連グループ教材へのリンクを使い、 「この用語が属する大きな分野」を俯瞰してから戻ってくると、 知識が一段抽象化された形で定着します。 用語ページは点、 グループ教材は線、 概念マップは面 — 三層を往復しながら学習を進めてください。

本ページの内容に不足を感じたら、 相関ページ(correlation.html)を参照基準として、 ご自身の解釈を加筆していくことを推奨します。 教材の完成形ではなく、 学習者自身の理解の出発点として位置付けてください。

最後に、 SSDSE-B-2026 の 47 都道府県データは「N=47 と少ない」という構造的制約があります。 統計検定の漸近近似が崩れる場面、 単一の県(東京都・沖縄県)が全体傾向を支配する場面、 標準誤差が過小評価される場面 — これらは本ページの随所で繰り返し注意喚起しました。 「実データの小ささを軽視しない」 という姿勢が、 実務でのデータサイエンティストの基本姿勢です。