🔖 キーワード索引 — 交絡を多角的に理解する
交絡(confounding)は因果推論の最重要概念です。 関連キーワードを難易度別に整理しました。
🟢 基礎キーワード(まず押さえる)
交絡因子(confounder) :原因と結果の両方に影響する第三の変数。 たとえば「アイス売上 → 溺死」の交絡因子は「気温」。
疑似相関 (spurious correlation) :因果関係がないのに統計的相関だけがある状態。 交絡が主因。
因果関係 vs 相関 :「相関は因果を含意しない」という統計の最重要金言。
説明変数の制御 :交絡因子を重回帰に含める、 層別解析する、 マッチングする等の対処法。
無作為割り付け(randomization) :交絡を期待値レベルで完全に消すゴールドスタンダード。
観察研究 vs 実験研究 :観察研究は交絡を完全には排除できない。 実験研究は randomization で防ぐ。
🟡 中級キーワード
因果ダイアグラム(DAG, directed acyclic graph) :変数間の因果関係を矢印で図示。 交絡パスを視覚化。
バックドアパス(backdoor path) :処置から結果に至る、 因果でない経路。 これを閉じることが因果推定の鍵。
傾向スコア(propensity score) :処置を受ける確率。 マッチングや IPW で交絡を制御。
差の差分法(DID, difference-in-differences) :時間と群の二重差で交絡を除去する準実験手法。
回帰不連続デザイン(RDD) :閾値前後でランダム化が成立するという仮定で因果推定。
シンプソンのパラドックス :層別解析と全体解析で逆の結論が出る現象。 交絡の極端例。
🔴 上級キーワード
do 演算子(Pearl の介入計算) :「もし強制的に X=x にしたら」という反実仮想の数学的表現。
操作変数法(IV, instrumental variable) :観測できない交絡があっても、 外生変数を使って因果推定。
媒介変数(mediator)と衝突点(collider) :制御すべきでない変数。 制御すると逆にバイアスを増やす。
選択バイアス(selection bias) :サンプル選択時点で生じるバイアス。 衝突点制御と同じ構造。
潜在結果モデル(Rubin causal model) :個体ごとに処置・対照両方の結果を仮想する枠組み。 ATE・ATT などの推定対象を明確化。
g-methods(g-formula、 marginal structural models) :時間変動交絡を扱う先進的手法。
💡 30秒で分かる結論
🍰 まずはやさしく
関係があるように見えるだけの「ニセモノ」のことです。
本当の原因を見つけるために使います。
アイスの売上と水難事故の関係が例です。
この章では交絡因子の正体を学びます。
定義 :説明変数 X と目的変数 Y の両方 に影響を与える第3の変数 CC の存在により、 X と Y の間に見かけ上の相関(疑似相関) が生まれる 古典例 :「アイス売上 ↔ 水難事故」の真の犯人は「夏の気温」本データの例 :「求人倍率 ↔ 死亡率」の真の犯人は「高齢化率」対処 :重回帰で交絡を制御、 操作変数法、 DiD、 パネル固定効果限界 :観察されない交絡は除去不可能 — 因果断言には実験デザインが必要
📖 もっと詳しく
2変数 A と B に強い相関があるとき、 (i) A が B を引き起こす、 (ii) B が A を引き起こす、 (iii) 両方を引き起こす第3の変数 C がある 、 の3パターンがあります。 (iii) のパターンを 交絡(confounding) といい、 観察データだけからは識別が難しい本質的問題です。
古典的な例: 「アイスクリームの売上」と「水難事故件数」には強い正相関があります。 だからといって「アイスが水難事故を起こす」とは誰も思わない。 真の犯人は「夏の気温」という第3変数 — 暑い日にはアイスも売れるし、 海・川での事故も増える。 アイスと水難事故の相関は 疑似相関(spurious correlation) です。 もう1つの古典例が「コーヒーをよく飲む人ほど肺がんが多い」— これも真の犯人は「喫煙」で、 コーヒーを飲みながらタバコを吸う人が多かった時代のデータでは、 喫煙がコーヒー摂取と肺がんの両方に結びついて見かけの相関を作っていました。
本サイトの実例: 47都道府県のデータで「有効求人倍率と死亡率 」を単純に相関させると、 r = +0.308 で p < 0.05 の有意な正の相関が出ます。 「景気が良い県ほど死亡率が高い?!」と読みたくなりますが、 これも疑似相関。 真の犯人は「高齢化率」 — 高齢化が進んだ地方では、 求職者が減って求人倍率は上がりやすく、 同時に死亡率も上がる。 高齢化率を統計的に制御すると、 求人倍率の効果は消えます。
対処法: (i) 重回帰 で交絡変数を説明変数として明示的に入れる(最も基本)、 (ii) 操作変数法(IV) で外生的変動を取り出す、 (iii) 差分の差分法(DiD) で時間不変の交絡を吸収、 (iv) パネル固定効果モデル で個体固有効果を吸収。 ただし観測されていない交絡(隠れた変数) は完全には排除できないのが社会科学の宿命。
📍 あなたが今見ているもの
🍰 まずはやさしく
分析のときに注意すべき「隠れた原因」のことです。
データの読み間違いを防ぐために使います。
スマホの利用時間と成績の関係などで考えます。
このページでは定義や対策について読みます。
論文で「交絡変数を制御 」「疑似相関 」「spurious correlation 」と書かれている部分。 因果推論で最も重要な概念。
交絡因子 とは:AとBの両方に影響を与える第3の変数C。Cの存在によりAとBに「見かけの相関」が生まれる(疑似相関)。
本ページでは「confounding」を扱う。 統計データ分析コンペティション (2026) の教材で、 SSDSE-B-2026 (47 都道府県 × 複数年 × 100 超列) の実データを使った再現可能な学習を目指す。
「confounding」は統計・データサイエンスの体系における重要概念のひとつ。 本ページは「定義・直感・数式・実装・落とし穴・関連手法」の 6 視点で構成され、 各視点は独立して読めるが順序通り読むと体系的な理解が得られる。
🎨 直感で掴む
🍰 まずはやさしく
裏で操っている「黒幕」のような存在です。
直感的に仕組みを理解するために使います。
求人倍率と死亡率の例で考えます。
なぜ見かけ上の関係が生まれるかを図で読みます。
「求人倍率と死亡率」の正相関は、 両者が共通して「高齢化率」と関係しているために発生する疑似相関(2023 年度・47 都道府県)。 高齢化率を制御すると効果はほぼ消える:単回帰の求人倍率の係数 2.94(p = 0.035)が、 高齢化率を加えた重回帰では 0.30(p = 0.40)になる。
左図:「求人倍率 vs 死亡率」の単純な散布図では、 確かに右上がりの関係(r=+0.31)。 「景気の良い県は死亡率が高い」と読みたくなる。
右図:ただし「求人倍率 vs 高齢化率」を見ると、 こちらも正の相関がある(r=+0.29 と弱めだが、 向きは同じ)— 高齢化が進んだ地方では求職者が少なく、 求人倍率が高くなりやすい。 一方で高齢化率と死亡率の相関は r=+0.97 と非常に強い(図には無いが同じデータで計算できる)。
つまり「高齢化率」という第3変数が、 「求人倍率」「死亡率」の両方を動かしているため、 求人倍率と死亡率に見かけの相関が出ているだけ。 これが交絡(confounding)の構造。
🎓 因果推論の階段:観察 → 介入 → 反実仮想
Judea Pearl の「因果のはしご」によると、 因果推論には3段階あります:
関連付け(観察) :「X と Y は相関する」 — 本サイトのほぼ全ての分析がここ介入 :「もし X を操作したら Y はどう変わるか」 — ランダム化実験で達成反実仮想 :「もし過去に X がこうだったら、 Y はどうなっていたか」 — DiD や IV が近づく観察データだけからの「因果」は本質的にレベル1。 重回帰で交絡を制御しても 「観察されない交絡」 が残るリスクは消えません。 だから論文の結論部では「相関を示した」「関連を観察した」と慎重に書き、 「因果関係」は控えめに表現するのがプロの作法です。
🎨 直感で掴む — 交絡 (Confounding)
交絡は「X と Y の両方に影響する第三の変数 Z があるとき、 X と Y の相関を Z が作り出してしまう 」現象。 「アイス売上 ↑ と水難事故 ↑」が真夏(気温)で繋がるのが典型例。 SSDSE-B-2026 でも、 A1101(人口)と L3221(消費支出)の相関を A1303(高齢人口)が交絡する可能性がある。
💡 学習のコツ :上の比喩は厳密ではない点に注意。 交絡 の定義は次の「📐 数式」で押さえ、 「🧮 実値で計算」で A1101(人口)と L3221(消費支出)の相関に A1303(高齢人口)が交絡する例を、 SSDSE-B-2026 の 47 都道府県データで実際に確認しましょう。
交絡 (Confounding) は「因果推論」カテゴリの中核概念。 初めて触れる読者は、 まずこの「🎨 直感」セクションだけ通読し、 必要になった時点で「📐 数式」「🐍 Python」「⚠️ 落とし穴」へ戻る読み方が定着しやすいです。
🔬 数式を言葉で読み解く — 数式を「言葉」に翻訳
上の数式を眺めるだけでは身につかないので、 各記号がどんな役割 を担っているかを言葉で押さえます。 「数式を音読する習慣」がつくと、 論文や教科書を読むスピードが体感で 2 倍ほど上がります。
$P(Y \mid X)$(右辺)— 観察して分かる分布
「X がたまたまこの値だった集団で、 Y はどう分布するか」。 記号 $\mid$ は「〜を条件として(given)」と読む。 相関・回帰など、 観察データの分析はすべてこちら側。
$P(Y \mid \text{do}(X))$(左辺)— 介入したときの分布
「全員の X を強制的に この値に設定したら、 Y はどう分布するか」。 因果効果の定義そのもの。 ランダム化実験が測っているのはこちら。
$\text{do}(\cdot)$ — Pearl の介入演算子
「観察する」と「操作する」を区別するための記号。 do を付けると、 X に向かって流れ込む矢印(Z → X など)を全部切断した世界を考えることになる。
$Z$ — 交絡変数(confounder)
X と Y の両方 に影響する第三の変数(DAG では X ← Z → Y)。 SSDSE-B-2026 の例なら「高齢化率」。 Z がこの位置にあるとき、 左辺と右辺は一致しなくなる。
$\ne$ — 両辺のズレ=交絡バイアス
「観察された関連」と「介入したときの効果」の差。 このズレを重回帰・層別・マッチング等で埋めるのが交絡制御。 Z を正しく制御できれば両辺は一致する。
📚 補足 :同じ記号でも分野・教科書によって意味が違うことがあります(例: $\hat{y}$ は予測値だが、 統計の文脈では推定量を意味することも)。 不明確なときは、 必ずその文書の記号定義表 を確認しましょう。
🧮 SSDSE-B-2026 実値計算例 — 47 都道府県で交絡を見抜く
合成データではなく公的統計を念頭に、 交絡因子が引き起こす疑似相関とその制御例を具体的な数値で示します。
① 「婚姻の多い県ほど死亡率が低い」?
47 都道府県で「婚姻率(人口千対)」と「粗死亡率(人口千対)」の相関を取ると、 高齢化という第3変数のために強い負の相関 が出ます。
🎯 解説: 2023 年度 47 都道府県で、 婚姻率(A9101/A1101×1000)・粗死亡率(A4200/A1101×1000)・高齢化率(A1303/A1101×100)の 3 つの単相関を並べ、 婚姻率と粗死亡率の負の相関が高齢化率という第 3 の変数で説明できるかを見る計算メモ。
📋 コピー # 単相関
r(婚姻率, 粗死亡率) ≈ -0.85
→ 「婚姻の多い県ほど死亡率が低い」
# しかし、 これは疑似相関
# 交絡因子:高齢化率
r(婚姻率, 高齢化率) ≈ -0.90(高齢化が進む県ほど婚姻が少ない)
r(高齢化率, 粗死亡率) ≈ +0.97 で非常に強い
→ つまり「死亡率は高齢化率でほぼ決まる」
📥 入力例: data/raw/SSDSE-B-2026.csv(2023 年度・47 都道府県)
A1101: 総人口
A1303: 65歳以上人口
A4200: 死亡数
A9101: 婚姻件数
📤 計算メモなので実行出力は無い(3 つの相関は後の Python 実装 ① で作る列から再計算できる)
💬 読み方: 婚姻率と粗死亡率の相関 −0.845 だけを見ると「結婚の多い県ほど死亡が少ない」と読めてしまう。 しかし高齢化率は婚姻率と −0.897、 粗死亡率と +0.972 で結び付いており、 高齢化の進んだ県ほど婚姻が少なく死亡が多いという構造だけで −0.845 の大半を説明できる。 3 つの相関はいずれも 2023 年度の実測値と小数 3 桁で一致する。
② 重回帰で交絡を制御
# 単回帰:粗死亡率 ~ 婚姻率 → 婚姻率の傾き -3.95
# 重回帰:粗死亡率 = β₀ + β₁·婚姻率 + β₂·高齢化率
# 重回帰の結果(SSDSE-B-2026, 2023 実測)
β₁(婚姻率)≈ +0.63 ← 符号が逆転!(p≈0.09 で有意でなくなる)
β₂(高齢化率)≈ +0.69
→ 高齢化率を制御すると、 婚姻率の死亡率への効果はほぼ消える
→ これが偏回帰係数の意味
→ 高齢化率という交絡因子が、 婚姻率 vs 粗死亡率 の見かけの相関を作っていた
💡 単相関と偏回帰係数で符号が反転する(−3.95 → +0.63 のように向きが変わる)のは、 強い交絡が存在する典型的なサイン です。 単回帰と重回帰で係数の符号・大きさが大きく食い違ったら、 「どの第三変数が両方を動かしているのか」を疑ってください。
③ シンプソンのパラドックスの再現
# 仮想例:医療機関 A と B の手術成功率
# A 病院 全体:70%(700/1000)
# B 病院 全体:80%(800/1000)
# → B の方が成績良い?
# 重症度で層別すると
A 病院 軽症:95%(475/500)、 重症:45%(225/500)
B 病院 軽症:90%(720/800)、 重症:40%(80/200)
→ 軽症でも重症でも A 病院の方が高い!
# 理由:A 病院は重症患者が多い、 B 病院は軽症が多い
# 「重症度」が交絡因子
④ 偏相関係数の計算
🎯 解説: 上の 3 つの単相関から、 高齢化率を固定したときの婚姻率と粗死亡率の偏相関を、 公式どおりに手で計算する。
📋 コピー 1
2
3
4
5
6
7
8
9
10
11
12
13 # 偏相関 r(X, Y | Z) = (r_XY - r_XZ·r_YZ) / sqrt((1-r_XZ²)(1-r_YZ²))
# 例:X = 婚姻率、 Y = 粗死亡率、 Z = 高齢化率
r_XY = -0.845 (単相関)
r_XZ = -0.897 (婚姻率 vs 高齢化率)
r_YZ = +0.972 (高齢化率 vs 粗死亡率)
r(X,Y|Z) = (-0.845 - (-0.897)·0.972) / sqrt((1-0.897²)(1-0.972²))
= (-0.845 + 0.872) / sqrt(0.1954 · 0.0552)
= 0.027 / 0.1039
≈ +0.26 ← 単相関 -0.845 から符号が反転
高齢化率を制御すると婚姻率と死亡率の
見かけの強い負相関はほぼ消える
📥 入力例: data/raw/SSDSE-B-2026.csv
目的変数: 粗死亡率(A4200/A1101 × 1000)
説明変数: 婚姻率(A9101/A1101 × 1000), 高齢化率(A1303/A1101 × 100)
📤 計算メモなので実行出力は無い(後の Python 実装 ② の pingouin で検算できる)
💬 読み方: 分子は −0.845 + 0.872 = 0.027 で、 単相関のほとんどが高齢化率を経由した成分(0.897 × 0.972 ≈ 0.872)で打ち消される。 分母 0.1039 も小さいので偏相関は +0.26 と符号が反転するが、 これは「婚姻が多いほど死亡が多い」ではなく、 高齢化率を固定すると関係がほとんど残らないことを示す。 後の pingouin の出力は r = 0.255、 95% 信頼区間 [−0.04, 0.51]、 p = 0.088 で、 0 と区別できない。
注:偏相関係数は、 同一データから計算した 3 つの r に対しては必ず −1〜+1 に収まります。 上の例では実データ(SSDSE-B-2026, 2023)から求めた r_XY=−0.845、 r_XZ=−0.897、 r_YZ=+0.972 が相関行列として整合するため、 偏相関は +0.26 と正しく求まります。 単相関 −0.845 が偏相関 +0.26 へと大きく変化(符号反転)したことが、 高齢化率という強い交絡の存在を示しています。 実務では statsmodels や pingouin で実データから直接計算してください。
⑤ 傾向スコアマッチングの簡易例
🎯 解説: 「人口減少県」を処置とみなし、 高齢化率・所得・進学率で傾向スコアマッチングしたとき群間の差がどう縮むかを、 仮想の結果で示す計算メモ(実データでの実装は後の Python 実装 ③)。
📋 コピー # 「人口減少県」を処置とみなし、 制御変数(高齢化率・所得・進学率)でマッチング
# ロジスティック回帰で傾向スコア p̂(X) を推定
仮想結果 :
群間直接比較 → 死亡率の差 + 3.1
傾向スコアマッチング後 → 死亡率の差 + 0.4
→ ほぼ高齢化率の差で説明できた
📥 入力(仮想)
処置: 人口減少県(1)/それ以外(0)
制御変数: 高齢化率・所得・進学率
結果: 粗死亡率
📤 計算メモなので実行出力は無い(数値は仮想)
💬 読み方: 仮想の数値では、 群をそのまま比べた死亡率の差 +3.1 が、 傾向スコアの近い県どうしを組にすると +0.4 まで縮む。 縮んだ 2.7 は処置の効果ではなく、 処置群に高齢化の進んだ県が多いという構成の違いだったと読む。 後の ③ は処置を「高齢化率が中央値超」に変えて実データで同じ手順を踏んだもので、 素の差 3.27 が ATT 1.93 に縮む。
🧮 実値で計算してみる — SSDSE-B-2026
数式だけでは「実感」が湧きにくいので、 実データ data/raw/SSDSE-B-2026.csv(47 都道府県 × 12 年)で 1 度手計算してみると理解が定着します。
SSDSE-B-2026 (2023) で A1101 と L3221 の単純相関 r ≈ 0.33。 A1303(高齢人口)も A1101 と強く相関(r≈0.99)し、 L3221 とも相関(r≈0.32)するため、 偏相関で A1303 を制御すると A1101→L3221 のパス係数が変動する。 偏相関 ρ(A1101, L3221 | A1303) ≈ 0.12 と推定でき、 見かけの相関(r ≈ 0.33)は約 3 分の 1 に縮小する — この縮んだ分が A1303 経由で作られていた成分。
都道府県 A1101 総人口 A1303 65 歳以上 L3221 消費支出
東京都 14,086,000 3,205,000 341,320
神奈川県 9,229,000 2,390,000 306,565
大阪府 8,763,000 2,424,000 271,246
愛知県 7,477,000 1,923,000 300,221
埼玉県 7,331,000 2,012,000 344,092
千葉県 6,257,000 1,756,000 306,943
上記は SSDSE-B-2026 (2023) からの抜粋。 手計算で確認した値が、 後述の Python 実装で得る値と一致することを確認すると、 「数式とコードの対応関係」がクリアに見えるようになります。
🧮 数式に値を入れて手で計算する: 交絡を層別で除く
合成データでアイス売上と溺死件数の相関、 気温で層別すると消える例を計算する。
Step 1: 全体の相関 (季節混在)
i アイス x 溺死 y 気温
1 20 2 低 2 30 3 低 3 80 10 高 4 90 11 高 5 100 10 高
Step 2: 全体相関 (見せかけ)
r(x,y) ≈ +0.977 (強い正の相関)
Step 3: 気温で層別 (高温群のみ)
高温 3 件: x=[80,90,100], y=[10,11,10]
平均からの偏差 x: −10, 0, +10 / y: −1/3, +2/3, −1/3
偏差の積の和 = (−10)(−1/3) + 0 + (+10)(−1/3) = 0 → r_high = 0
→ 気温をそろえると、 アイス売上と溺死件数の相関は消える
🐍 Python で再現
import numpy as np
x = np . array ([ 20 , 30 , 80 , 90 , 100 ])
y = np . array ([ 2 , 3 , 10 , 11 , 10 ])
print ( f "全体 r = { np . corrcoef ( x , y )[ 0 , 1 ] : .3f } " )
xh , yh = x [ 2 :], y [ 2 :]
print ( f "高温群 r = { np . corrcoef ( xh , yh )[ 0 , 1 ] : .3f } " )
📤 実行結果
全体 r = 0.977
高温群 r = 0.000
💬 手計算(全体 r ≈ 0.977、 高温群 r = 0)と Python 出力が一致。 5 日を混ぜると、 気温の低い 2 日と高い 3 日の差だけで強い正の相関が生まれるが、 高温の 3 日の中ではアイスが売れても溺死は増えず相関は 0 になる。 見せかけの相関を作っていたのは気温(交絡因子)である。
🐍 Python 実装のバリエーション — pandas / statsmodels / causalml
① 単相関と重回帰での係数比較
🎯 解説: 2023 年度 47 都道府県で、 粗死亡率を婚姻率だけで回帰したときの係数と、 高齢化率を加えた重回帰での婚姻率の係数を statsmodels で比べる。
📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行)
都道府県 A1101(総人口) A1303(65歳以上人口) A4200(死亡数) A9101(婚姻件数)
北海道 5,092,000 1,681,000 75,120 17,281
東京都 14,086,000 3,205,000 137,241 71,774
沖縄県 1,468,000 350,000 15,110 6,316
…(全 47 行)
📋 コピー 1
2
3
4
5
6
7
8
9
10
11
12
13 import pandas as pd
import statsmodels.api as sm
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023] # 2023年・47都道府県
df['粗死亡率'] = df['A4200'] / df['A1101'] * 1000
df['婚姻率'] = df['A9101'] / df['A1101'] * 1000
df['高齢化率'] = df['A1303'] / df['A1101'] * 100
# 単回帰:粗死亡率 ~ 婚姻率
m1 = sm.OLS(df['粗死亡率'], sm.add_constant(df[['婚姻率']])).fit()
print('単回帰の婚姻率係数:', round(m1.params['婚姻率'], 3))
# 重回帰:粗死亡率 ~ 婚姻率 + 高齢化率(交絡制御)
m2 = sm.OLS(df['粗死亡率'], sm.add_constant(df[['婚姻率','高齢化率']])).fit()
print('重回帰の婚姻率係数:', round(m2.params['婚姻率'], 3))
📥 入力例: data/raw/SSDSE-B-2026.csv(2023 年度・47 都道府県)
A1101: 総人口
A1303: 65歳以上人口
A4200: 死亡数
A9101: 婚姻件数
📤 実行例(実測)
単回帰の婚姻率係数: -3.947
重回帰の婚姻率係数: 0.631
💬 読み方: 婚姻率だけで回帰すると係数は −3.947 で、 婚姻率が人口千人あたり 1 件高い県は粗死亡率が約 3.9 低く見える。 高齢化率を加えると係数は +0.631 と符号が反転し、 p 値も約 0.09 で 0 と区別できなくなる。 同じ重回帰で高齢化率の係数は +0.686 で、 粗死亡率の県差はほぼ年齢構成で決まっている。
② 偏相関係数(pingouin)
🎯 解説: pingouin の partial_corr で、 高齢化率を制御したときの婚姻率と粗死亡率の偏相関と、 その 95% 信頼区間・p 値を求める(上の計算メモ ④ の検算)。
📋 コピー import pingouin as pg
# 高齢化率を制御した婚姻率 vs 粗死亡率 の偏相関
result = pg . partial_corr ( data = df , x = '婚姻率' , y = '粗死亡率' , covar = '高齢化率' )
print ( result )
📥 入力例: data/raw/SSDSE-B-2026.csv
目的変数: 粗死亡率(A4200/A1101 × 1000)
説明変数: 婚姻率(A9101/A1101 × 1000), 高齢化率(A1303/A1101 × 100)
📤 実行例(実測)
n r CI95 p_val
pearson 47 0.254667 [-0.04, 0.51] 0.087638
💬 読み方: 偏相関は r = 0.255 で、 計算メモ ④ の手計算 +0.26 と一致する。 95% 信頼区間 [−0.04, 0.51] が 0 をまたぎ p = 0.088 なので、 高齢化率を固定した後に婚姻率と粗死亡率の間に残る関係は、 47 県では 0 と区別できない。 単相関 −0.845 の強さは、 ほぼすべて高齢化率を経由したものだった。
③ 傾向スコアマッチング(scikit-learn + 自前マッチング)
🎯 解説: 高齢化率が中央値を超える 23 県を処置群とし、 婚姻率と消費支出(L3221)から傾向スコアをロジスティック回帰で推定して、 処置群の各県に傾向スコアの最も近い対照県を(重複を許して)当て、 粗死亡率の差(ATT)を求める。
📋 コピー 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 from sklearn.linear_model import LogisticRegression
import numpy as np
df [ 'treated' ] = ( df [ '高齢化率' ] > df [ '高齢化率' ] . median ()) . astype ( int )
X = df [[ '婚姻率' , 'L3221' ]]
y_t = df [ 'treated' ]
# 傾向スコア推定
ps_model = LogisticRegression ( max_iter = 1000 ) . fit ( X , y_t )
df [ 'propensity' ] = ps_model . predict_proba ( X )[:, 1 ]
# 最近傍マッチング
treated = df [ df [ 'treated' ] == 1 ]
control = df [ df [ 'treated' ] == 0 ]
matches = []
for _ , t in treated . iterrows ():
idx = ( control [ 'propensity' ] - t [ 'propensity' ]) . abs () . idxmin ()
matches . append (( t . name , idx ))
matched_treated = df . loc [[ m [ 0 ] for m in matches ]]
matched_control = df . loc [[ m [ 1 ] for m in matches ]]
print ( 'ATT:' , matched_treated [ '粗死亡率' ] . mean () - matched_control [ '粗死亡率' ] . mean ())
📥 入力例: data/raw/SSDSE-B-2026.csv(2023 年度・47 都道府県、 ① で作った df)
処置: 高齢化率が中央値超(23 県)
共変量: 婚姻率(A9101/A1101×1000)、 消費支出 L3221
結果: 粗死亡率(A4200/A1101×1000)
📤 実行例(実測)
ATT: 1.9331901340389983
💬 読み方: 処置群と対照群の粗死亡率を素のまま比べると 15.77 − 12.50 = 3.27 の差があるが、 婚姻率と消費支出の近い県どうしで比べた ATT は 1.93 に縮む。 ただし共変量の婚姻率そのものが高齢化の結果でもあるので、 1.93 を「高齢化の効果」と読むには、 どの変数で調整すべきかを DAG(⑤)で確かめる必要がある。
④ IPW(逆確率重み付け)
🎯 解説: ③ で求めた傾向スコア p の逆数(処置群は 1/p、 対照群は 1/(1−p))を重みにして、 群ごとの重み付き平均の差として粗死亡率の IPW 推定値を求める。
📋 コピー df [ 'weight' ] = df . apply (
lambda r : 1 / r [ 'propensity' ] if r [ 'treated' ] == 1 else 1 / ( 1 - r [ 'propensity' ]),
axis = 1
)
# 重み付き平均
ipw_treated = ( df [ df [ 'treated' ] == 1 ][ '粗死亡率' ] * df [ df [ 'treated' ] == 1 ][ 'weight' ]) . sum () / df [ df [ 'treated' ] == 1 ][ 'weight' ] . sum ()
ipw_control = ( df [ df [ 'treated' ] == 0 ][ '粗死亡率' ] * df [ df [ 'treated' ] == 0 ][ 'weight' ]) . sum () / df [ df [ 'treated' ] == 0 ][ 'weight' ] . sum ()
print ( 'IPW ATE:' , ipw_treated - ipw_control )
📥 入力: ③ の df(treated 列と propensity 列を追加済み)
📤 実行例(実測)
IPW ATE: 2.7845640949371226
💬 読み方: IPW による差は 2.78 で、 素の差 3.27 より小さく、 ③ のマッチングによる ATT 1.93 より大きい。 IPW が推定するのは 47 県全体に対する平均効果(ATE)、 マッチングは処置群に対する効果(ATT)なので、 値が違うこと自体はおかしくない。 傾向スコアは 0.004〜0.948 と 0 や 1 に近い県があり、 1/p や 1/(1−p) が大きな重みになってその県に推定が引っ張られやすい点に注意する。
⑤ DAG の可視化(pgmpy + networkx)
🎯 解説: 高齢化率 → 粗死亡率、 高齢化率 → 婚姻率、 婚姻率 → 粗死亡率 の 3 本の矢印からなる因果グラフ(DAG)を networkx で描き、 dag.png に保存する。
📋 コピー 1
2
3
4
5
6
7
8
9
10
11
12 import networkx as nx
import matplotlib.pyplot as plt
dag = nx . DiGraph ()
dag . add_edges_from ([
( '高齢化率' , '粗死亡率' ),
( '高齢化率' , '婚姻率' ),
( '婚姻率' , '粗死亡率' ),
])
pos = nx . spring_layout ( dag , seed = 42 )
nx . draw ( dag , pos , with_labels = True , node_size = 2500 , node_color = 'lightblue' , arrows = True )
plt . savefig ( 'dag.png' , dpi = 150 )
📥 入力例: data/raw/SSDSE-B-2026.csv
目的変数: 粗死亡率(A4200/A1101 × 1000)
説明変数: 婚姻率(A9101/A1101 × 1000), 高齢化率(A1303/A1101 × 100)
📤 このブロックは標準出力には何も出さない
💬 読み方: 標準出力は無く、 3 つのノードと 3 本の矢印の図が dag.png に保存される。 高齢化率から婚姻率と粗死亡率の両方へ矢印が出ているので、 婚姻率 → 粗死亡率 の効果を測るには高齢化率で条件付けて裏口の経路を塞ぐ必要がある、 と図から読める。 ① の重回帰と ② の偏相関は、 この図に沿った調整になっている。
⑥ E-value(未測定交絡の頑健性)
🎯 解説: 観察された相対リスク RR に対し、 その関連を打ち消すのに必要な未測定の交絡の強さ(E-value = RR + √(RR(RR−1)))を、 RR = 2.0 と 3.0 で計算する。
📋 コピー def evalue ( rr ):
"""観察された相対リスク rr に対し、 必要な交絡因子の強さ"""
if rr < 1 :
rr = 1 / rr
return rr + ( rr * ( rr - 1 )) ** 0.5
print ( f '観察RR=2.0 を覆すには E-value = { evalue ( 2.0 ) : .2f } 倍の交絡が必要' )
print ( f '観察RR=3.0 を覆すには E-value = { evalue ( 3.0 ) : .2f } 倍の交絡が必要' )
📥 入力: 観察された相対リスク RR = 2.0、 3.0(数値例)
📤 実行例(実測)
観察RR=2.0 を覆すには E-value = 3.41 倍の交絡が必要
観察RR=3.0 を覆すには E-value = 5.45 倍の交絡が必要
💬 読み方: RR = 2.0 の関連は、 処置とも結果とも 3.41 倍以上の強さで結び付く未測定の交絡因子が無ければ説明し尽くせない。 RR = 3.0 なら必要な強さは 5.45 倍に上がる。 E-value が大きいほど、 見落とした交絡で結論がひっくり返りにくいと読む。
⑦ DoWhy で因果効果推定
🎯 解説: DoWhy で「処置(高齢化率が中央値超)→ 粗死亡率」の効果を、 高齢化率と婚姻率を共通原因とするバックドア調整の線形回帰で推定し、 ランダムな共通原因を足しても推定値が変わらないかで頑健性を確かめる(③ の df を使う)。
📋 コピー 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 # pip install dowhy
from dowhy import CausalModel
model = CausalModel (
data = df ,
treatment = 'treated' ,
outcome = '粗死亡率' ,
common_causes = [ '高齢化率' , '婚姻率' ]
)
identified = model . identify_effect ()
estimate = model . estimate_effect ( identified , method_name = 'backdoor.linear_regression' )
print ( estimate )
# 頑健性チェック
refute = model . refute_estimate ( identified , estimate , method_name = 'random_common_cause' )
print ( refute )
📥 入力: ③ の df(treated・粗死亡率・高齢化率・婚姻率 の列)
📤 実行例(dowhy 0.14 での実測、 抜粋)
Realized estimand
b: 粗死亡率~treated+婚姻率+高齢化率
Target units: ate
Estimate
Mean value: 0.14031531844555367
Refute: Add a random common cause
Estimated effect:0.14031531844555367
New effect:0.1406486633695947
p value:1.0
💬 読み方: 推定値は 0.140 で、 ③ の ATT 1.93 よりずっと小さい。 共通原因に高齢化率そのものを入れているので、 「高齢化率が中央値を超えるか」という処置の効果は、 高齢化率を固定したうえで中央値の前後に残るわずかな差しか測れないためである(処置が共通原因の関数になっていて、 処置群と対照群の重なりが無い)。 ランダムな共通原因を足しても 0.1406 とほぼ変わらないが、 この検査はこうした設計の誤りまでは見つけない。 New effect は乱数を使うので実行ごとに下の桁が変わる。
🐍 Python 実装 — 交絡 (Confounding)
公的統計(SSDSE-B-2026)を題材に、 最小限の Python コードで 交絡 (Confounding) を動作させます。 まずはこのまま実行してみてください。
📋 コピー 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 # 交絡 (Confounding) を SSDSE-B-2026 で実行する最小コード
import pandas as pd
df = pd . read_csv ( 'data/raw/SSDSE-B-2026.csv' , encoding = 'cp932' , skiprows = [ 1 ])
df = df [ df [ 'SSDSE-B-2026' ] == 2023 ] # 2023 年のみ抽出
print ( df . shape ) # (47, 112)
print ( df [[ 'Prefecture' , 'A1101' , 'A1303' , 'L3221' ]] . head ())
import pandas as pd
import numpy as np
cols = [ 'A1101' , 'A1303' , 'L3221' ]
C = df [ cols ] . astype ( float ) . corr ()
print ( C )
# 偏相関 ρ(x,y|z)
def partial ( x , y , z ):
r_xy = C . loc [ x , y ]; r_xz = C . loc [ x , z ]; r_yz = C . loc [ y , z ]
return ( r_xy - r_xz * r_yz ) / np . sqrt (( 1 - r_xz ** 2 ) * ( 1 - r_yz ** 2 ))
print ( '偏相関(A1101,L3221|A1303)=' , partial ( 'A1101' , 'L3221' , 'A1303' ))
📤 実行例(実測)
(47, 112)
Prefecture A1101 A1303 L3221
0 北海道 5092000 1681000 296888
12 青森県 1184000 417000 263371
24 岩手県 1163000 407000 298536
36 宮城県 2264000 662000 305541
48 秋田県 914000 357000 272086
A1101 A1303 L3221
A1101 1.000000 0.990979 0.332548
A1303 0.990979 1.000000 0.320735
L3221 0.332548 0.320735 1.000000
偏相関(A1101,L3221|A1303)= 0.1158568407119759
💬 総人口と世帯の消費支出の相関 0.333 は、65 歳以上人口で調整した偏相関では 0.116 まで小さくなる。ただし総人口と 65 歳以上人口の相関が 0.991 とほぼ同じ変数なので、ここでの「調整」は実質的に人口規模そのものを取り除いており、偏相関の分母 √(1−0.991²) が約 0.13 と小さく数値が不安定になる。交絡因子として調整するなら、人数ではなく高齢化率のように結果と原因の両方に影響しうる別の性質の変数を選ぶのが筋である。
▶ 実行 を押せばこのページの中でそのまま動きます(ライブラリもデータも同梱済みで、 準備は要りません)。 手元の Python に移して動かすときは pip install matplotlib numpy pandas scikit-learn scipy seaborn statsmodels が必要です。 読んでいるデータは data/raw/SSDSE-B-2026.csv。 日本語を含むので encoding='cp932' の指定を落とさないでください。
⚠️ よくある落とし穴
❌ 制御変数を入れさえすれば因果が分かる、 ではない
観測されていない交絡(隠れた変数) が必ず残るのが社会科学の宿命。 重回帰でできるのは「観測した交絡を統計的に消す」だけ。 これを忘れて因果を断定するのは過剰解釈。
❌ 「相関がある = 因果関係がある」
3つの可能性が常にある:(i) X→Y、 (ii) Y→X(逆因果)、 (iii) C→X & C→Y(交絡)。 観察データだけからは識別できない。
❌ 「サンプルが大きいから因果が分かる」
n を増やしても交絡は解消されない(むしろ統計的に有意になりやすくなり、 誤った因果断定を助長する)。 因果には実験デザインかしっかりした自然実験が必要。
✅ 観察データから因果に近づく方法
(i) 準実験デザイン (DiD、 IV、 回帰不連続デザイン RDD)、 (ii) 傾向スコアマッチング 、 (iii) 経済学的・生物学的な事前理論 による解釈、 (iv) 感度分析 で「観察されない交絡がどれだけ強ければ結果が反転するか」を評価。
📖 包括的解説 — この概念を完全マスター
📍 学習の3ステップ
定義を理解する :この概念は何か? 数式や条件を確認
具体例を見る :実データ(SSDSE 等)で計算してみる
応用する :自分のデータに適用、 結果を解釈
🔧 Python実装パターン
🎯 解説: 2023 年度 47 都道府県の総人口(A1101)・65 歳以上人口(A1303)・消費支出(L3221)の散布図行列を seaborn の pairplot で描く。 describe() も呼んでいるが、 結果を print していないので何も表示されない。
📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行)
都道府県 A1101(総人口) A1303(65歳以上人口) L3221(消費支出(二人以上の世帯))
北海道 5,092,000 1,681,000 296,888
東京都 14,086,000 3,205,000 341,320
沖縄県 1,468,000 350,000 251,222
…(全 47 行)
📋 コピー 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 # 基本パターン
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' , skiprows = [ 1 ])
df = df [ df [ 'SSDSE-B-2026' ] == 2023 ] # 2023 年度の 47 都道府県に絞る
# 基本統計量
df . describe ()
# 可視化
sns . pairplot ( df [[ 'A1101' , 'A1303' , 'L3221' ]])
plt . show ()
📥 入力例: data/raw/SSDSE-B-2026.csv(2023 年度に絞った 47 行)
A1101: 総人口
A1303: 65歳以上人口
L3221: 消費支出(二人以上の世帯)
📤 このブロックは標準出力には何も出さない
💬 読み方: 標準出力は無く、 3 × 3 の散布図行列が表示される。 総人口と 65 歳以上人口はほぼ一直線に並び(相関 0.991)、 消費支出はどちらとも相関 0.33 前後の緩い関係なので、 この 2 つの人口変数を同時に調整に入れると、 多重共線性で係数が不安定になる。
📚 統計概念マップでの位置
このページの上にある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()
🚧 一般的な落とし穴と対策
外れ値の影響 :散布図・ 箱ひげ図で確認、 ロバスト手法も検討
サンプルサイズ不足 :power analysis で事前に確認
仮定の違反 :正規性、 独立性、 等分散性をチェック
多重比較問題 :補正(Bonferroni、 FDR)を適用
p-hacking :事前登録(pre-registration)で防ぐ
因果と相関の混同 :観察データから因果結論を出さない
📊 結果報告の標準フォーマット
点推定 :得られた値
不確実性 :信頼区間または標準誤差
サンプルサイズ :n を明記
効果量 :実質的な意義
p値 :統計的有意性
仮定の確認 :診断プロット
🌐 関連分野での応用
マーケティング :A/Bテスト、 顧客分析
医療 :臨床試験、 疫学研究
金融 :リスク管理、 ポートフォリオ
製造 :品質管理、 工程最適化
公共政策 :効果評価、 計画立案
研究 :仮説検証、 探索的解析
🎓 さらに学ぶための文献
Wasserman "All of Statistics"
Hastie, Tibshirani & Friedman "The Elements of Statistical Learning"
Gelman & Hill "Data Analysis Using Regression"
VanderPlas "Python Data Science Handbook"
🔗 統計用語ネットワーク
この概念は、 他の多くの統計概念と密接に関連しています。 ジャストインタイム型学習では、 必要に応じて関連用語へジャンプしながら全体像を構築します。
主要な関連概念のグループ
グループ
主要概念
記述統計 平均、 中央値、 最頻値、 分散、 標準偏差、 共分散、 相関係数
可視化 ヒストグラム、 散布図、 箱ひげ図、 ヒートマップ
推測統計 標本平均、 標準誤差、 信頼区間、 p値、 有意水準
確率分布 正規分布、 t分布、 χ²分布、 F分布、 二項分布
仮説検定 t検定、 F検定、 χ²検定、 ノンパラ検定
回帰 単回帰、 重回帰、 OLS、 Ridge、 LASSO
分類 ロジスティック回帰、 決定木、 SVM、 k-NN
教師なし学習 クラスタリング、 PCA、 因子分析
時系列 ARIMA、 VAR、 指数平滑法、 自己相関
因果推論 DiD、 IV、 傾向スコア、 交絡変数
前処理 標準化、 正規化、 欠損値処理、 多重共線性対策
評価 R²、 残差、 CV、 RMSE、 効果量
学習順序の推奨
記述統計(平均、 分散、 標準偏差)
可視化(ヒストグラム、 散布図)
確率分布(正規分布)
推測統計(標準誤差、 信頼区間、 p値)
仮説検定(t検定、 χ²検定)
相関と回帰(単回帰、 重回帰)
多変量解析(PCA、 クラスタリング)
機械学習(決定木、 RF、 NN)
時系列・因果推論(応用)
📝 実践練習 — SSDSE-B-2026 で挑戦
初級課題
東北6県の家計食料費の基本統計量を計算
食料費のヒストグラムを描く
食料費と教育費の散布図を描く
都道府県を「東日本/西日本」に分け、 平均を比較
中級課題
家計支出 5項目で相関行列を作成、 ヒートマップ可視化
食料費 → 教育費の単回帰を実行、 残差分析
家計5項目で PCA を実施、 バイプロット表示
k-means (k=3) で都道府県をクラスタリング、 解釈
上級課題
地域別の家計パターンに有意差があるか ANOVA で検定
重回帰で教育費を予測、 多重共線性を VIF で確認
Ridge/LASSO で正則化、 CV で α を最適化
階層クラスタリングと Ward 法で都道府県を分類、 デンドログラム作成
⚠️ 交絡対策の落とし穴と典型ワークフロー
📋 交絡因子の発見チェックリスト
チェック項目 具体例 満たさない場合
原因と結果の両方に関係する 年齢が運動量と疾患リスクの両方に影響 交絡因子ではない
中間変数 (媒介) ではない 運動 → 体重 → 疾患の体重は中間 統制すると効果を消してしまう
時間的に原因より先行 介入前の喫煙歴は交絡 後発変数は collider の可能性
合流点 (collider) ではない 入院は能力と病気の合流点 統制するとバイアス導入
DAG で明示的にモデル化 事前に図を描いて議論 統制すべき変数が曖昧に
🚨 誤解 TOP 5
誤解 正しい理解
「全部統制すれば安全」 collider/中間変数を統制するとバイアス導入。 DAG で「統制すべき集合」を識別
「観察研究では因果不可能」 適切な手法 (PSM/IV/DID/RD) で因果推論可能。 RCT が常にベストではない
「相関 ≠ 因果だから無意味」 相関は仮説の出発点。 交絡を考えて因果関係に近づける
「未観測交絡は無視 OK」 感度分析で頑健性検証。 E-value で「どれだけ強い未観測交絡が必要か」評価
「重回帰すれば因果が出る」 回帰係数は条件付き相関。 DAG なしには因果解釈不可
🔄 交絡対策ワークフロー
DAG 描画 : ドメイン知識から原因・結果・交絡候補・媒介・合流点を識別
統制すべき集合の決定 : backdoor 基準で「最小十分調整集合」を特定 (DAGitty 等のツール活用)
データ収集 : 統制集合の変数を全て観測。 観測不能なら IV/DID を検討
共変量バランス確認 : 介入群と対照群で統制変数の分布が近いか (Standardized Mean Difference)
主分析 : 回帰調整/PSM/IPW のうち適切な手法を選択 (DAG・データ規模に応じて)
感度分析 : 未観測交絡への頑健性を E-value、 Rosenbaum バウンドで評価
結果報告 : 推定効果、 95%CI、 統制した変数集合、 仮定、 限界を明示
📚 ケーススタディ: SSDSE-B-2026 で交絡を可視化
「求人倍率と死亡率の正相関 (r=+0.31)」は典型的な交絡例です。 高齢化率を統制すると、 偏相関は r_partial ≈ 0.02 程度まで縮小し、 ほぼゼロになります。 これは「景気と死亡率には因果関係はないが、 共通因子の高齢化率が両者を動かしている」という解釈を支持します。
分析 相関 r 解釈
単相関 (求人倍率 × 死亡率) +0.31 見かけの相関 (交絡含む)
偏相関 (高齢化率を統制) +0.02 統制後ほぼ消滅 → 擬似相関
高齢化率 × 求人倍率 +0.55 高齢化進行県ほど求人多い
高齢化率 × 死亡率 +0.72 高齢化率は死亡率に強影響
回帰調整 (死亡率 ~ 求人倍率 + 高齢化率) β_求人 ≈ 0 求人倍率の死亡率への独立効果なし
※ 本ページの各節に登場する r(例:高齢化率×死亡率の 0.72、 0.91、 0.97)は、 節ごとに想定する年次・変数定義(粗死亡率か、 求人倍率か県民所得か等)が異なる説明用の概数 のため完全には一致しません。 数値そのものよりも「交絡因子を統制すると見かけの相関が消える」という構造を掴んでください。
このケースは「DAG → 偏相関 → 回帰調整」という標準ワークフローで擬似相関を見破る典型例として教育的価値が高い分析結果です。 同じ手順を他の SSDSE 変数ペア (例えば「婚姻率(A9101/A1101)と粗死亡率(A4200/A1101)」「消費支出(L3221)と総人口(A1101)」など) にも応用することで、 一見驚くべき相関の多くが第三因子で説明できることが学習者に強く印象づけられます。
🔬 因果推論の重要概念まとめ
交絡対策を体系的に理解するには、 周辺概念との関係を整理することが重要です。 下表は因果推論で頻出する 5 つの重要概念を、 交絡と比較する形でまとめています。
概念 定義 対処 DAG 上の位置
交絡 (Confounder) 原因と結果の共通因子 統制する X ← Z → Y
媒介 (Mediator) 原因と結果の中間因子 統制しない (効果を分解する時のみ) X → M → Y
合流点 (Collider) 原因と別変数の共通結果 統制しない (したらバイアス導入) X → C ← Y'
選択バイアス 標本選択による歪み 補正重み付け or 設計変更 合流点で条件付け
情報バイアス 測定誤差 測定改善 or 補正法 DAG 外 (測定モデルで対応)
交絡だけを意識しがちですが、 媒介・合流点・選択バイアスも因果推論の落とし穴です。 「とにかく統制すれば良い」という発想は、 媒介や合流点で逆に正しい因果効果を消したり歪めたりするため、 必ず DAG ベースで「統制すべき変数集合」を判定する必要があります。
📝 実務における交絡対策の優先順位
研究設計段階で防ぐのが最善 : ランダム化、 マッチング、 自然実験の活用を検討
主要な交絡因子から優先的に観測 : 全ての交絡を観測するのは現実的でないため、 効果サイズが大きいと予想される変数から
感度分析を必ず併用 : 「未観測交絡がどれだけ強くないと結論が覆らないか」を E-value で評価
結果は範囲で報告 : 点推定だけでなく、 様々な統制集合や手法での結果を併記して頑健性を示す
仮定を透明化 : DAG、 並行トレンド仮定、 IV の妥当性など、 因果解釈の根拠となる仮定を明記
交絡対策は「100% の正解」がない領域です。 重要なのは、 自分の分析が どの仮定の下でどこまでの主張ができるか を明示し、 限界を含めて報告することです。 これが学術的にも実務的にも信頼される因果推論の作法です。
🏥 領域別の交絡対策の典型パターン
領域によって典型的な交絡因子と対処手順が異なります。 以下に主要 5 領域の比較を示します。 自分の分析対象がどの領域に近いかを判断し、 該当領域のベストプラクティスを参考にすることが効率的です。
領域 典型的交絡因子 主流手法 代表ガイドライン
医療・疫学 年齢・性別・喫煙・併存疾患 RCT、 PSM、 IPW STROBE、 CONSORT
経済・政策評価 所得・教育・地域要因 DID、 IV、 RD What Works Clearinghouse
マーケティング 顧客特性・季節要因 A/B テスト、 PSM 業界別 (デジタル分析)
教育研究 家庭環境・先行学力 RD、 マッチング EEF Toolkit
社会科学 SES、 文化・地域要因 IV、 DID、 固定効果 ASA Statement
📤 各領域には独自のベストプラクティスとガイドラインが存在し、 査読論文の通過にはそれに準拠することが事実上の要件となっています。 自分の分析が学術発表や政策評価を意図する場合、 該当領域のガイドラインを事前に読み込むことが推奨されます。
🛠️ 因果推論ツール・ライブラリの主要選択肢
Python/R には因果推論を支援する成熟したライブラリ群があります。 用途に応じて以下を使い分けるのが定石です。
statsmodels (Python): 回帰調整、 固定効果モデル、 IV2SLS など基本的な計量経済モデルを網羅。 教育目的にも実務にも幅広く使える。
DoWhy (Microsoft): DAG ベースの因果推論フレームワーク。 「識別 → 推定 → 反証」の 4 ステップで体系的に分析できる。
causalml (Uber): 機械学習を用いた異質処置効果 (HTE) の推定。 マーケティング A/B テストで活用例多数。
EconML (Microsoft): Double Machine Learning や Causal Forest など最新手法を実装。 経済学者・データサイエンティスト向け。
R 系 (MatchIt, twang, did): 統計家コミュニティで定番。 査読論文での引用が多く、 学術的信頼性が高い。
ツール選択は分析目的・スキルセット・再現性要件で決まります。 教育目的なら statsmodels、 産業 A/B テストなら causalml、 学術論文向けなら R 系または DoWhy が一般的な選択です。
🎓 学習リソースの優先順位 (おすすめ順)
因果推論を体系的に学びたい場合、 入門 → 中級 → 上級の段階で異なる教材が推奨されます。 以下に主要な日本語・英語リソースをまとめます。
入門 : Pearl 著『因果推論の科学』(日本語訳あり) — DAG とバックドア基準を平易な事例で導入。 文系・初学者にも親しみやすい。
中級 : Hernán & Robins『Causal Inference: What If』(無料 PDF 配布) — 疫学者向けの定番テキスト。 PSM/IV/G-methods を体系的にカバー。
中級 : Cunningham『Causal Inference: The Mixtape』(無料公開版) — 経済学者向け。 DID/RD/IV を実装例とともに学べる。
上級 : Imbens & Rubin『Causal Inference for Statistics, Social, and Biomedical Sciences』 — Potential Outcome フレームワークの決定版。 厳密性重視。
実装重視 : Facure『Causal Inference for The Brave and True』(無料 Web 公開) — Python で実装例豊富。 ハンズオン学習に最適。
📚 これらを順に学習すると、 半年〜1 年で「DAG → 識別戦略 → 推定 → 感度分析 → 報告」の一連のワークフローが回せるようになります。 統計学のバックグラウンドがあれば独学でも到達可能です。 加えて、 専門家コミュニティ (twitter の #CausalInference タグ、 国内では計量経済学会・統計関連学会連合大会) でのディスカッション参加も理解を深めるのに非常に有効です。 教科書だけでは見えない実務的な「やりがちな失敗」「査読で指摘されやすいポイント」が議論されています。 学習の終盤では、 自身の研究プロジェクトで仮説を立て、 DAG を描き、 因果効果を推定し、 限界を含めて報告する一連のサイクルを実際に経験することが、 最も効果的な定着方法となります。 模擬データではなく公的データ (SSDSE、 e-Stat、 政府統計の総合窓口) を活用すると、 現実的なノイズや欠損とも向き合えるため、 教育効果が格段に高まります。
⚠️ 交絡に関する落とし穴 — 実務で必ず引っかかるポイント 7 選
① 衝突点(collider)を制御してバイアスを増やす
「制御すれば交絡が消える」は誤解です。 X → Z ← Y の構造で Z は衝突点 であり、 制御すると X と Y の間に擬似的な相関を生み出します(Berkson のパラドックス)。 例:「俳優として有名 → 有名人賞受賞 ← 演技力」で「有名人賞」を条件にすると、 「俳優として有名」と「演技力」が無関係に見える。 DAG を描いて、 制御すべき変数を慎重に選ぶ必要があります。
② 媒介変数(mediator)を交絡と勘違いして制御する
X → M → Y の構造で M は媒介変数 です。 これを制御すると、 X の Y への「直接効果」しか得られず、 M を介した「間接効果」を見落とします。 例:「運動 → 体重減少 → 健康改善」で「体重」を制御すると、 運動の健康効果が消えて見える。 制御すべきは「処置以前に決まる変数」のみです。
③ 観測できない交絡を無視する(未測定交絡)
重回帰で「年齢」「性別」「所得」を制御しても、 観測できていない交絡因子(遺伝、 生活習慣、 動機) は除外できません。 観察研究では「未測定交絡が存在する可能性」を必ず仮定し、 結果の頑健性を sensitivity analysis(E-value)で評価することが推奨されます。 因果と断言したいなら、 ランダム化比較試験や自然実験(DID、 RDD)を検討してください。
④ シンプソンのパラドックスを「サンプル数の問題」と誤認
シンプソンのパラドックスは標本サイズの問題ではなく、 交絡の構造的問題 です。 各群のサンプル数を増やしても解消しません。 重要なのは「層別すべき変数(交絡因子)の特定」と「適切な集約(重み付け平均、 直接標準化)」。 マーガリンと総死亡率の関係、 治療法の比較などで現実に頻発します。
⑤ 「重回帰に入れれば全て解決」と思い込む
重回帰は交絡制御の 1 手段に過ぎず、 万能ではない 。 (i) 線形の仮定が正しい必要、 (ii) 交絡因子を「測定」していないと制御不能、 (iii) 多重共線性で係数が不安定化、 (iv) 衝突点や媒介変数を入れると逆効果、 などの限界があります。 マッチング、 IPW、 IV、 DID、 RDD など多様な手法を理解し、 因果ダイアグラムに基づき選びましょう。
⑥ 反実仮想(counterfactual)を観測値と混同する
「もし喫煙していなかったら肺がんになったか」という反実仮想は原理的に観測不可能 です。 観測されるのは「喫煙したか」「肺がんになったか」のペアだけ。 因果推論はこの反実仮想を統計的に推定する技術で、 RCT は最も信頼できる近似手段、 観察研究はあくまで「仮定の下での近似」だと理解する必要があります。
⑦ 時間変動交絡(time-varying confounding)を見落とす
縦断研究では、 処置自体が次の時点の交絡因子に影響する 状況が頻発します。 例:「血圧降下薬服用 → 血圧低下 → 次の時点の処方変更」。 通常の重回帰では正しく扱えず、 g-formula、 marginal structural models、 g-estimation など g-methods が必要。 疫学・経済学の縦断研究では必須の知識です。
⚠️ よくある落とし穴 — 交絡 (Confounding)
交絡 (Confounding) を使うときに初学者が踏みやすい 失敗パターン。 1 度経験してしまえば次から避けられますが、 先に知っておくに越したことはありません。
❌ 交絡を見落として因果断定
「相関は因果でない」の典型。 介入実験・DAG・操作変数で対処する。
❌ コライダーをコントロール
Z が X・Y の子 (共通結果)の場合、 制御すると逆に偽の相関が生まれる。
❌ 変数追加だけで OK と思う
全ての交絡を観測できる前提が必要。 観測されない交絡は層別では消せない。
🛡 交絡固有の防御策 :「分析前に DAG (因果ダイアグラム) を紙に描き、 X→Y の経路と Z→X, Z→Y の経路を分離して「どれを止めるべき変数か」を決める 」「傾向スコアマッチング後は SMD (Standardized Mean Difference) < 0.1 でバランス確認 」「未観測交絡の感度分析 (Rosenbaum bounds, E-value) を併記して "結論の頑健性" を示す 」の 3 点を守れば、 因果断定の誤り・コライダー誤調整・観測交絡偏重の罠を回避できます。
🎮 触って理解する
交絡変数 Z(例: 年齢層・地域規模など)が X と Y の両方 に影響すると、
各層の中では X と Y が正の関係 なのに、
全体を一緒くたに集計すると逆向き(負)に見える ——これが
疑似相関 の代表例
Simpson のパラドックス です。
下の図をドラッグ (横方向=交絡の強さ/縦方向=層内の傾き)するか、
スライダーを動かすと、層別散布図(層ごとに色分け)・層内回帰直線(各層の色) ・
全体回帰直線(黒い破線) がリアルタイムに更新され、数値も正確に再計算されます。
※ 図は概念理解のための模式データ であり、実測値ではありません(乱数シード固定で再現可能)。
💡 試してみよう : 「交絡の強さ」を 0 まで下げると層のズレが消え、全体と層内の傾きが一致します(逆転なし)。強くすると各層は右上がりのまま、全体だけが右下がりに反転します。「層内の傾き」を負にすれば、逆パターン(各層は負・全体は正)も再現できます。
🎨 直感 — なぜ逆転するのか(共通原因)
交絡変数 Z は X と Y の共通原因 です。図で言うと、Z の層が変わるたびに点群の「かたまり」がまるごと上下左右に移動します。層のかたまりが右下がりに並んでいると、点全体をまとめて 1 本の直線で近似したときに、層内の本当の傾き(右上がり)ではなく、層間の並び方(右下がり)を拾って しまう。これが集計による符号反転の正体です。層で色分けすれば、各層内では一貫して右上がりであることが一目で分かります。
⚠️ よくある落とし穴 — 集計の罠と「調整すべき変数」
集計の罠 : 「全体の相関」だけを見て因果を語るのは危険。層別(相関 を層ごとに計算)すると符号が逆になることがある。
調整すべきは交絡だけ : Z が X・Y の共通原因 なら調整(層別・重回帰 への投入)が正しい。しかし Z が X→Z→Y の中間変数(メディエータ) や X・Y の共通結果(コライダー) の場合、調整するとむしろバイアスが生まれる。「変数を足せば安心」ではない。
観測されない交絡 : 層別・回帰調整で消せるのは観測できた 交絡だけ。未観測交絡には 操作変数法 や 差分の差分法 、感度分析が必要。
🚀 発展 — 層別・回帰調整・DAG・バックドア基準
層別解析 (stratification) : Z の各層内で X-Y 関係を推定し、層をまたいで統合する。上の図の「層内回帰直線」がまさにこれ。層が少数カテゴリのときに有効。
回帰調整 : 重回帰 に Z を投入すると、偏回帰係数 βX は「Z を一定にしたときの X の純効果」を近似する。連続的な交絡にも対応できる。
DAG(因果ダイアグラム) : X→Y の矢印に加え、Z→X と Z→Y の矢印を描くと Z が交絡(共通原因)だと視覚的に判定できる。分析前に紙に描くのが定石。
バックドア基準 (back-door criterion) : X と Y の間の「裏口経路」(X←Z→Y のように矢印を逆流する経路)を、Z を条件付け(調整)することで塞ぐ。すべてのバックドア経路を塞ぐ変数集合で調整すれば、因果効果を識別できる。コライダーを誤って開かないことが要点。
📚 統計学習の総合ガイド
🎯 学習目標
このページの概念をマスターすることで、 以下のスキルが身につきます:
定義と公式を正確に理解
適切な使用場面を判断
Python で実装し、 結果を可視化
仮定の確認と診断
結果の解釈と報告
限界と注意点の理解
関連手法との使い分け
📊 SSDSE-B-2026 データの構造
このコンペの主要データセット(SSDSE-B-2026)の構造:
47都道府県 × 過去複数年(パネル形式)
112列の社会経済指標
人口、 出生、 死亡、 婚姻、 経済、 教育、 環境、 家計など多次元
政府統計を統合した信頼性の高いデータ
🔍 主要な変数群
カテゴリ
変数例
人口 総人口、 年齢別人口、 性別人口
人口動態 出生数、 死亡数、 合計特殊出生率、 婚姻数
気候 気温、 降水量、 降水日数
教育 幼小中高校数、 教員数、 生徒数、 大学進学率
経済 求職件数、 求人件数、 旅館数
医療 病院数、 診療所数、 歯科診療所
家計 消費支出、 食料費、 住居費、 教育費等の項目別
💡 ジャストインタイム型学習
このガイドは「必要なときに必要な知識 」を提供する設計:
論文中の用語をクリック → 該当の用語解説へジャンプ(ポップアップ)
概念マップで関連用語を辿る
包含マップで体系を把握
ツリーマップで全体を俯瞰
Python コードをコピーして実行
SSDSE データで実際に試す
🛠️ Python データサイエンス環境
🎯 解説: 環境の準備と読み込み確認。ライブラリを import して日本語フォントを設定し、SSDSE-B-2026 を読み込む。2023 年度の 47 都道府県に絞って、高齢化率・粗死亡率・婚姻率(いずれも人口あたり)の相関行列を出し、交絡の構図を先に確かめる。pip の行はコメントにしてあるので、ターミナルで 1 回だけ実行する。
📋 コピー 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 # 事前に(ターミナルで 1 回だけ): 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-B は cp932。skiprows=[1] で 2 行目の日本語の項目名を飛ばし、1 行目の英字コードを列名にする)
df = pd . read_csv ( 'data/raw/SSDSE-B-2026.csv' , encoding = 'cp932' , skiprows = [ 1 ])
print ( df . shape ) # 47 都道府県 × 12 年度(2012〜2023)
# 県を単位にするので 2023 年度の 47 都道府県に絞る
d = df [ df [ 'SSDSE-B-2026' ] == 2023 ] . copy ()
d [ '高齢化率' ] = d [ 'A1303' ] / d [ 'A1101' ] * 100 # 交絡因子の候補
d [ '粗死亡率' ] = d [ 'A4200' ] / d [ 'A1101' ] * 1000 # 人口千対
d [ '婚姻率' ] = d [ 'A9101' ] / d [ 'A1101' ] * 1000 # 人口千対
print ( d [[ '高齢化率' , '粗死亡率' , '婚姻率' ]] . corr () . round ( 3 ))
📥 入力例: data/raw/SSDSE-B-2026.csv(cp932。1 行目が英字コード、2 行目が日本語の項目名、その下に 47 都道府県 × 12 年度 = 564 行。新しい年度が先に並ぶ)
📤 実行例(実測)
(564, 112)
高齢化率 粗死亡率 婚姻率
高齢化率 1.000 0.972 -0.897
粗死亡率 0.972 1.000 -0.845
婚姻率 -0.897 -0.845 1.000
💬 2023 年度の 47 県で、粗死亡率と婚姻率の相関は −0.845 と強い負の関係に見える。しかし高齢化率が粗死亡率と 0.972、婚姻率と −0.897 で両方に強く効いており、高齢化率で両方を回帰した残差どうしの相関(偏相関)を取ると +0.255 に変わる。死亡が多い県で結婚が少ないのは、高齢化という共通の原因が作った見かけの関係と読むのが自然。
🌟 効果的なEDAテンプレート
🎯 解説: 形・列の型・欠損数・要約統計を表示し、 数値列のヒストグラムと相関ヒートマップ(target を渡せば散布図行列も)を描く quick_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
25
26
27
28 def quick_eda ( df , target = None ):
"""探索的データ分析の基本テンプレート"""
print ( f "Shape: { df . shape } " )
print ( f " \n Column types: \n { df . dtypes } " )
print ( f " \n Missing values: \n { df . isnull () . sum () } " )
print ( f " \n Basic 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 :
cols = list ( numeric_cols [: 5 ])
if df [ target ] . dtype == 'O' : # 文字列の列なら色分け(hue)に使う。hue の列も渡す
sns . pairplot ( df [ cols + [ target ]], hue = target )
else :
sns . pairplot ( df [ cols ])
plt . show ()
📥 入力: quick_eda(df, target=None) に渡す DataFrame(ここでは未実行)
📤 このブロックは標準出力には何も出さない
💬 読み方: 関数を定義するだけなので何も表示されない。 SSDSE-B-2026 の全列にそのまま使うと、 数値 110 列でヒストグラムが 110 枚、 ヒートマップが 110 × 110 のマスになって読めないので、 交絡を確かめたい列(例: 婚姻率・粗死亡率・高齢化率)に絞った DataFrame を渡す。
📈 報告書テンプレート
分析結果を報告する際の標準的な構成:
背景・目的 :なぜこの分析が必要か
データ :出所、 サンプルサイズ、 期間
方法 :使用した統計手法、 仮定
結果 :図表、 統計量、 検定結果
解釈 :結果が何を意味するか
限界 :分析の制約
結論 :要点まとめ、 今後の課題
交絡 (Confounding) の全体像 を学ぶには、 横断的な教材から入るのが効率的:
🧩 交絡因子 — Round 264 補強 (理解度チェック + 数式読み解き)
🔬 数式を言葉で読み解く (層別解析の重み付き効果)
交絡因子 $Z$ で層別したときの真の効果 $\beta_{X \to Y}$ は、 各層 $z$ の効果を $Z$ の分布で重み付けして算出します。
$$ \beta_{X \to Y}^{\text{adjusted}} = \sum_{z} P(Z = z) \cdot \beta_{X \to Y \mid Z = z} $$
記号の意味:
$P(Z=z)$ は層 $z$ の人数比率 (重み)、 $\beta_{X \to Y \mid Z=z}$ は層 $z$ の中だけで観察した $X$ → $Y$ の効果。
全体での単純相関は「層別効果」と「層の偏り」が混ざってしまうため、 $Z$ で層別してから重み付き平均をとることで、 $Z$ が説明する分を取り除いた効果が得られます (= 標準化、 共変量調整)。
これが回帰モデルに $Z$ を入れる行為と数学的に等価です。
✅ 理解度チェック (1 分で答える)
「アイスクリーム売上が多い日は溺死事故が多い」という観察は交絡因子で説明できますか? その変数は何ですか?
交絡因子と中間因子 (mediator) は、 因果関係上、 どこが違うかを一文で答えてください。
回帰分析で交絡因子 $Z$ を制御するには、 どの変数をモデルに加えればよいですか?
このコードでやること : SSDSE-B-2026 で「人口規模 (交絡因子)」を制御する前後で「婚姻件数 (A9101) → 出生数 (A4101)」効果の係数がどう変わるかを比較する。
📥 入力データ (SSDSE-B-2026 抜粋):
A1101(人口) A9101(婚姻件数) A4101(出生数)
東京都 14,086,000 71,774 86,348
大阪府 8,763,000 38,513 55,292
神奈川県 9,229,000 38,176 53,991
... ... ... ...
import pandas as pd
import statsmodels.api as sm
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023] # 2023年・47都道府県
# モデル1: 制御なし(婚姻件数 → 出生数)
m1 = sm.OLS(df['A4101'], sm.add_constant(df[['A9101']])).fit()
# モデル2: 人口規模(A1101)を交絡因子として制御
m2 = sm.OLS(df['A4101'], sm.add_constant(df[['A9101', 'A1101']])).fit()
print('制御なし 婚姻件数係数:', round(m1.params['A9101'], 4))
print('人口制御後 婚姻件数係数:', round(m2.params['A9101'], 4))
📤 実行例(実測)
制御なし 婚姻件数係数: 1.3022
人口制御後 婚姻件数係数: 0.4174
💬 婚姻件数だけで出生数を回帰すると係数は 1.3022 で「婚姻 1 件あたり出生 1.3 人」に見えるが、総人口を加えると 0.4174 と約 3 分の 1 に縮む。婚姻件数と総人口の相関は 0.989 で、単回帰の係数の大部分は「人口の多い県ほど婚姻も出生も多い」という規模の効果を拾っていた。調整後も婚姻件数の係数は p ≈ 0.0005 で残るが、説明変数どうしがこれほど強く相関していると係数の標準誤差(0.112)が大きく、人口あたりの率に直したモデルでも確かめたい。
📌 関連用語クイック参照
因果関係 — 交絡を取り除いた先にある到達点
重回帰分析 — 交絡因子を制御する典型ツール
自然実験 — 観察データで交絡を回避する別アプローチ
🗺️ 統計手法選択フローチャート
Q1: 何を知りたい?
記述したい → 平均、 分散、 ヒストグラム
比較したい → t検定、 ANOVA、 χ²検定
関係を見たい → 相関、 回帰
予測したい → 回帰、 機械学習
分類したい → ロジスティック回帰、 SVM、 RF
グループ分けしたい → クラスタリング
次元を減らしたい → PCA、 因子分析
因果関係を知りたい → RCT、 IV、 DiD、 PSM
Q2: データの種類は?
連続値 → t検定、 ANOVA、 線形回帰
カテゴリ → χ²検定、 ロジスティック回帰
順序 → ノンパラ検定、 順位回帰
カウント → ポアソン回帰、 負の二項回帰
時系列 → ARIMA、 VAR、 状態空間
パネル → 固定効果、 ランダム効果
Q3: サンプルサイズは?
n < 30 :ノンパラ、 ベイズ、 ブートストラップ
30 ≤ n < 200 :古典的検定、 単純な回帰
n ≥ 200 :複雑なモデル、 機械学習
n ≥ 10000 :深層学習も可能
Q4: 仮定は?
正規性 :満たす → パラメトリック / 満たさない → ノンパラ
独立性 :必須 / 違反 → クラスター調整、 時系列モデル
等分散性 :満たす → OLS / 違反 → WLS、 ロバスト
📏 効果量の参照表
p値だけでなく効果量も併記するのが現代統計の標準。 主要な指標と Cohen の解釈基準:
統計量
効果量
小
中
大
2群平均差 Cohen's d 0.2 0.5 0.8
相関 r 0.1 0.3 0.5
線形回帰 R² 0.02 0.13 0.26
ANOVA η² (eta²) 0.01 0.06 0.14
χ² Cramér's V 0.1 0.3 0.5
ロジスティック Odds Ratio 1.5 2.5 4.0
🖼️ 交絡の追加図解 — DAG とブロッキング戦略
交絡 (confounding) は「原因 X と結果 Y の両方に影響する第三変数 Z 」によって生じます。 因果ダイアグラム (DAG) で X ← Z → Y というパスが存在すると、 X と Y の単純な相関は 本当の因果効果 + Z 経由の擬似効果 に分解されます。 これをブロックする (Z を統制する) のが交絡対策の本質です。
図: 全体では正の相関に見えるが、 Z でグループ分けするとグループ内では一貫した関係がない (シンプソンのパラドックス的構造)。 2023 年度・47 都道府県の有効求人倍率と死亡率を、 交絡因子 Z = 高齢化率の 3 区分(低 22.8〜30.6%・中 30.6〜33.2%・高 33.3〜39.1%)で分けると、 全体の傾き 2.94(r = 0.31)に対し、 区分内の傾きは 1.50・0.39・−1.81 と向きもそろわない。 死亡率の差は主に区分の間(高齢化率の違い)で生じている。
図: 求人倍率 vs 死亡率の擬似相関 (高齢化率が共通因子)。 制御変数の重要性を直感的に示す典型例。
📊 交絡対策手法の比較表
手法 適用タイミング 必要前提 主な限界
ランダム化 (RCT) 設計段階 介入可能・倫理的に許容 コスト高・倫理的制約
層別化 (Stratification) 解析段階 交絡因子が観測されている 高次元では cell が空になる
マッチング 解析段階 十分なペア確保可能 サンプル数減少
回帰調整 解析段階 関数形が正しい 非線形性で誤り発生
傾向スコア (PSM) 解析段階 介入確率が推定可能 未観測交絡には無力
操作変数法 (IV) 解析段階 強い IV が存在 IV の妥当性証明が困難
DID (差の差) 解析段階 (パネル) 並行トレンド仮定 介入前後の比較対象必須
📤 ポイント: 観察研究では「ランダム化が使えない代わりに何で代用するか」が問われる。 観測された交絡因子は層別/回帰/PSM、 未観測は IV/DID/RD で対処するのが定石。
🗺️ 概念マップ — 3つの視点で体系を理解する
交絡因子 がデータサイエンスの体系の中でどこに位置するか を、 3つの異なる視点で可視化します。 同じ情報でも見方を変えると気付きが変わります。
📍 体系階層のパス
🌐 統計・データサイエンス › 因果推論 › 観察研究 › 疑似相関
① 🔗 関係マップ — 「他の手法とどう繋がっているか」
中心に 交絡因子 を置き、 そこから 相関係数・共分散・Spearman相関・単回帰 計 4 個の用語へ、 前提・兄弟・発展形といった関係を矢印で結んでいます。 線がどちら向きかを見れば、 先に読むべき用語 とあとから読む用語 が分かります。 ノードはドラッグ で動かせ、 ホイールでズーム 、 クリックでその用語のページへ遷移 します。
凡例: 現在の用語 上位カテゴリ 兄弟(並列) 前提 発展形 応用先 2階層先
② ⭕ 包含マップ — 「どのカテゴリに含まれているか」
大きな円が小さな円を包含 する Circle Packing 図。 「交絡因子」は緑色でハイライト 。
カテゴリ円をクリック :その内部にズームイン
白背景クリック :1階層戻る
用語円をクリック :詳細ページへ遷移
マウスホバー :階層パス表示
③ 🌳 ツリーマップ — 「面積で見るボリューム比較」
長方形を入れ子に分割した Treemap 図。 各分野の規模感 を面積で比較。 「交絡因子」は緑色でハイライト 。
カテゴリ矩形をクリック :その内部にドリルダウン
パンくず(上のリンク)クリック :その階層に戻る
用語矩形をクリック :詳細ページへ遷移
マウスホバー :階層パスと値を表示
🎯 3つのマップの使い分け
マップ
分かること
こんな時に見る
🔗 関係マップ 手法間の横の関係 (前提→発展→応用) 「次に何を学べばよい?」 学習順序の判断
⭕ 包含マップ 分類体系の入れ子構造 (上位⊃下位) 「この手法はどんなジャンルに属する?」
🌳 ツリーマップ 分野の規模比較 (面積=ボリューム) 「データサイエンス全体の俯瞰像」
💡 3 つの図は同じ位置関係を別の角度から描いています。 関係マップは 疑似相関 の隣に何が並ぶか を、 包含マップとツリーマップは 統計・データサイエンス → 観察研究 → 疑似相関 という入れ子の位置 を示します。 「観察研究には他に何があったか」を思い出したいときは包含マップを、 「次に何を読むか」を決めたいときは関係マップを開いてください。
🔗 隣接手法への橋渡し
「交絡」は処理と結果の両方に影響する第三変数で、 上流の DAG 描画 (因果構造の整理) と下流の調整方法 (層別・傾向スコア) を組まないと、 観察データの因果推論は全て見せかけになる。
上流で DAG により交絡経路を可視化し、 並列の RCT・操作変数法と比較して観察データの限界を把握し、 下流で傾向スコア・差分の差分 (DID) で調整すれば、 SSDSE 観察データから「政策効果」を妥当な精度で推定できる。
🌳 手法選択フロー
「confounding」を含む手法選択は、 データの性質・分析目的・運用制約の 3 軸で決まる。 以下に典型シナリオと対応する手法の組合せを示す。
典型シナリオ別の手法選択
シナリオ 重視する観点 候補手法
データが大規模 (n が多い、 高次元) 計算コスト / メモリ / 並列化が必要 高次元対応版 等
外れ値が多い / ノイズあり 頑健性 / 外れ値除去 / 中央値ベース 頑健版 等
解釈性を重視する 線形 / 木構造 / ルールベース 解釈重視版 等
予測精度を最優先する アンサンブル / ハイパラ調整 / 交差検証 標準手法 等
データが少ない 正則化 / ベイズ / 転移学習 / 簡素なモデル 小データ向け 等
リアルタイム/オンライン処理 ストリーミング / 軽量モデル / 逐次更新 高速版 等
選んだ後の検証ステップ
前処理確認 : 標準化 / 欠損処理 / カテゴリ変数のエンコード が適切か
ハイパラ調整 : 交差検証で安定する値を選ぶ
性能評価 : タスクに応じた指標 (RMSE / Accuracy / F1 / AUC / シルエット等) を複数併用
頑健性チェック : 別手法 / 別シードで結果が大きく違わないか確認
解釈 : 結果を分野知識と照らし合わせ、 意味のある発見になっているか検討
🎨 直感の深掘り — 「第3の変数」が相関をどう作るか
交絡のいちばん短い定義は「説明変数 X と結果 Y の両方 に影響する第3の変数 C 」です。C が両方を同じ向きに動かせば、X と Y は「一緒に上下する」ように見え、見かけの相関(疑似相関) が生まれます。X と Y の間に本当の因果の矢印が 1 本もなくても相関は出る——ここが「相関は因果を含意しない」の核心です。DAG(因果ダイアグラム)で書くと X ← C → Y の形。この「裏口経路(バックドア)」を C の統制で塞がない限り、X と Y の単純な関係は「真の効果 + C 経由の見せかけ」の合計になります。
大事なのは、交絡を統制しないと因果を誤る という一点です。単純相関だけを見て「X を動かせば Y が変わる」と読むと、実際には C を動かしただけ、あるいは何も因果がない、という誤りに陥ります。逆に、C を正しく統制(層別・回帰への投入・マッチング)できれば、見かけの成分が剥がれて、X → Y の純粋な関係に近づきます。
🧮 実データで「符号が反転する」例(SSDSE-B-2026, 2023, 47都道府県・実測)
既出の「婚姻率 × 死亡率」とは別の、年齢構造の変数を直接使わない 実例を1つ足します。一般旅券発行件数(人口千対, G5105/A1101×1000) と着工新設住宅床面積(人口1人当たり, H2600/A1101) を取ると、単純相関は r = +0.584 の中程度の正相関です。「パスポートをよく出す県ほど住宅もよく建つ」と読みたくなります。
🎯 交絡因子 = 高齢化率(A1303/A1101×100)
r(旅券発行, 住宅床面積) = +0.584 ← 見かけの正相関
r(旅券発行, 高齢化率) = -0.853 (若い県ほど旅券を多く発行)
r(住宅床面積, 高齢化率) = -0.779 (若い県ほど住宅を多く着工)
偏相関 r(旅券, 住宅 | 高齢化率) = -0.242 ← 符号が反転!
回帰でも同じ:
単回帰 住宅床面積 ~ 旅券発行 傾き +0.0047 (p<0.001)
重回帰 住宅床面積 ~ 旅券発行 + 高齢化率 傾き -0.0023 (p=0.105, 有意でなくなる)
高齢化率の傾き -0.0205 (p<0.001)
つまり「旅券と住宅の正相関」は両者の真の関係ではなく 、「若い(高齢化率の低い)県ほど、旅券発行も住宅着工も多い 」という高齢化率 を共通原因とする疑似相関でした。高齢化率を統制すると +0.584 の見かけの相関はゼロを飛び越えて弱い負(−0.242)に転じます。単純相関と偏相関で符号が反転するのは、強い交絡が存在する典型的なサイン です。
高齢化率の三分位で層別しても同じ構造が見えます(各層 n≈15〜16, 実測):若い層 r=+0.32/中位層 r=−0.10/高齢層 r=+0.26 と、層内では全体(+0.58)ほど強い正相関は残らず、層をまたぐ「並び」が全体の見かけの正相関を作っていたことが分かります。
※ 上の数値はいずれも data/raw/SSDSE-B-2026.csv(cp932, skiprows=[1], SSDSE-B-2026==2023 の 47 行)からの実測です。pd.read_csv(..., encoding='cp932', skiprows=[1]) で読み込み、numpy.corrcoef/statsmodels.OLS で再現できます。
⚠️ 落とし穴の深掘り(重要)— 「統制すればよい」ではない
交絡の最大の実務的な罠は、「とにかく変数を足して統制すれば因果が出る 」という思い込みです。統制は相手が交絡のときだけ正しく、相手を間違えると新たなバイアスを生みます 。以下は特に踏みやすい 7 点です。
❌ 未観測交絡は統制できない
重回帰・層別・マッチングで消せるのは「
観測できた 交絡」だけ。遺伝・動機・生活習慣・地域文化など測っていない共通原因は残り続けます。観察研究では「未測定交絡が存在しうる」を常に仮定し、頑健性を感応度分析(E-value 等)で示すのが作法。因果を断言したいなら実験デザイン(RCT)か自然実験(
DID ・
RDD ・
操作変数法 )を検討します。
❌ 統制しすぎ①:中間変数(媒介)を入れる
X → M → Y の M は媒介変数 であって交絡ではありません。M を統制すると X の間接効果 が消え、総効果を過小評価します。例:「運動 → 体重減少 → 健康改善」で体重を統制すると運動の健康効果が消えて見える。統制してよいのは「処置より時間的に先に決まる変数 」だけです。
❌ 統制しすぎ②:コライダー(衝突点)を入れる
X → C ← Y の C は X と Y の
共通結果 。ここで C を統制(または C で標本選択)すると、無関係だった X と Y に
偽の相関 が生まれます(Berkson の逆説)。
選択バイアス と同じ構造。「入院者だけ」「合格者だけ」を見ると変数が負相関に見える、が典型例。
❌ 交絡と媒介の区別を怠る
同じ「X・Y の両方に関係する変数」でも、原因側にあるなら交絡(統制する) 、結果への通り道なら媒介(原則統制しない) 。データの相関だけでは区別できず、時間順序とドメイン知識で DAG を描いて判断 するしかありません。
❌ 残差交絡(residual confounding)
交絡因子を入れても、粗いカテゴリ化 (例:年齢を10歳刻みでしか持っていない)や関数形の誤り (本当は非線形なのに線形で入れた)だと、統制しきれない成分が残ります。「変数名を入れた=完全に統制した」ではありません。連続変数はできるだけ連続のまま、非線形項やスプラインも検討します。
❌ 測定誤差のある交絡因子
交絡因子を
誤差込みで測っている と、統制は不完全になります(測定誤差の分だけ交絡が漏れる=残差交絡の一種)。自己申告の所得・喫煙量などが典型。
測定誤差 が大きい交絡因子ほど「入れても効いていない」ように見え、油断すると過小統制になります。
❌ 統計的統制の限界を過信する
重回帰・傾向スコア・IPW はいずれも「観測した交絡を、仮定した関数形の下で 」調整する道具にすぎません。サンプルを増やしても未観測交絡は消えず(むしろ偽の効果が有意になりやすい)、統制変数の選択が誤っていれば結果は歪みます。統計手法は DAG で決めた「統制すべき集合」を実行する道具であり、DAG の代わりにはならない ——これが要点です。
✅ 実務の指針
(i) 分析前にDAG を紙に描き 、交絡・媒介・コライダーを仕分ける。(ii) バックドア基準で「最小十分調整集合」を決める。(iii) 傾向スコア後は SMD(標準化平均差)で共変量バランスを確認。(iv) 未観測交絡は E-value・Rosenbaum バウンドで頑健性を報告。(v) 結論は「どの仮定の下でどこまで言えるか」を明示する。
🚀 発展 — DAG・バックドア基準から未観測交絡への対処まで
① DAG とバックドア基準(統制すべき集合の決め方)
バックドア経路 とは、X から Y へ「X に向かう矢印から逆流して」到達する非因果の経路(例:X ← C → Y)です。バックドア基準 は「(a) 調整集合 Z が X の子孫(=媒介・コライダーの下流)を含まず、(b) X と Y の間のすべてのバックドア経路を Z で塞ぐ」ことを要求します。これを満たす Z で調整すれば、観測データから因果効果 P(Y | do(X)) が識別できます。コライダーを誤って開かない(統制しない)ことが要点。DAGitty などのツールで「最小十分調整集合」を機械的に列挙できます。
② 観測した交絡への標準的手法
層別解析 :交絡因子の各層で X–Y 関係を推定し、層の重みで統合(直接標準化)。少数カテゴリの交絡に有効だが、高次元だと層が空になる。
回帰調整 :重回帰 に交絡因子を投入。偏回帰係数が「交絡を一定にしたときの純効果」を近似。関数形の仮定に依存。
傾向スコア :処置を受ける確率 p̂(X) を推定し、マッチング/層別/共変量化で交絡をまとめて調整。多数の交絡を1次元に圧縮できる。
IPW(逆確率重み付け) :傾向スコアの逆数で重み付けし、擬似的にランダム化された母集団を作る。極端な傾向スコアで重みが暴れる点に注意(トリミング/安定化重み)。
③ コライダー・媒介との区別(同じ「第3変数」でも扱いが逆)
DAG 上の位置 名前 統制すべきか
X ← C → Y(共通原因) 交絡 する(バックドアを塞ぐ)
X → M → Y(通り道) 媒介 総効果を見るなら統制しない
X → C ← Y(共通結果) コライダー 統制しない(開くと偽相関)
④ 未観測交絡に立ち向かう準実験デザイン
操作変数法(IV) :Y への経路が X 経由しかない外生変数(操作変数)を使い、観測できない交絡があっても 因果効果を推定。内生性 への標準的処方。
差分の差分法(DID) :処置群・対照群の前後差の差をとり、時間不変の交絡 を丸ごと吸収。並行トレンド仮定が鍵。
回帰不連続デザイン(RDD) :閾値の前後で「ほぼランダム割付」が成立すると仮定して、局所的な因果効果を推定。
自然実験 :制度変更や地理的境界など、研究者が介入せずとも準ランダムな変動が生じた状況を利用。
なお「causal-inference」「instrumental-variable」「collider」「mediator」「simpson」「e-value」といった単独ページは本用語集には未収録のため、ここでは本文中の解説で補っています(内部リンクは張っていません)。
⑤ E-value — 未測定交絡への感応度分析
E-value は「観測された関連(相対リスク RR)を完全に説明し尽くす ためには、未測定交絡因子が処置とも結果ともどれだけ強く 関連していなければならないか」を、最小の相対リスクで表す指標です。式は RR ≥ 1 のとき
$$ \text{E-value} = \mathrm{RR} + \sqrt{\mathrm{RR}\,(\mathrm{RR}-1)} $$
たとえば RR=2.0 なら E-value ≈ 3.41、RR=3.0 なら ≈ 5.45。値が大きいほど「そんなに強い未測定交絡はさすがに考えにくい」=結論が頑健、と読みます。RR が 1 未満(防御的関連)のときは 1/RR に置き換えて計算します。点推定だけでなく信頼区間の下限(1 に近い側)に対しても E-value を出すと、より慎重な頑健性評価になります。E-value は「未測定交絡を消す」ものではなく、「どれだけの強さが必要かを可視化して議論の土台にする」道具である点に注意してください。
🔗 交絡を深めるための関連ページ
交絡は 1 ページで閉じる概念ではありません。以下は本用語集内に実在する 関連ページです(未収録の概念はリンクを張らず本文で補足しています)。
因果関係 — 交絡を取り除いた先にある到達点。「相関 → 因果」への橋。
疑似相関 — 交絡が作り出す「見かけの相関」そのものの呼び名。
選択バイアス — コライダー統制と同じ構造で生じる、標本選択由来の歪み。
逆因果 — X→Y と思ったら Y→X。交絡と並ぶ「相関≠因果」の要因。
測定誤差 — 交絡因子を誤差込みで測ると残差交絡が生じる。
内生性 — 説明変数が誤差項と相関する問題。交絡の計量経済学的表現。
重回帰分析 — 観測した交絡を統制する最も基本的な道具。
操作変数法(IV) — 未観測交絡があっても因果に迫る手法。
差分の差分法(DID) — 時間不変の交絡を吸収する準実験デザイン。
回帰不連続デザイン(RDD) — 閾値前後の準ランダム性を利用。
自然実験 — 観察データで交絡を回避する設計上のアプローチ。
高齢化率 — 本ページの実データ例で一貫して交絡因子となる共通原因。