Mímisbrunnr知恵の泉

← 因果推論 一覧

🎓 レベル:基礎 | 重要度:A(必須)

📎 次に読む:潜在結果モデル | 数理:2変数の記述(散布図・共分散・相関係数)── 相関≠因果/rは直線関係しか測れない/外れ値1点で激変(統計)・クロス集計表・行/列比率・連関 ── 同じ表でも「何で割るか」で結論が変わる(統計)

要点(BLUF)

1. なぜ「相関=因果」と言えないのか

「アイスクリームの売上が増えると水難事故が増える」——両者は強く相関しますが、アイスが事故を起こすわけではありません。背後に気温という共通の原因があり、暑い日はアイスも売れるし水遊びも増えるだけです。

このように、処置 XX(アイス売上)と結果 YY(事故)の**両方に矢印を出している変数 CC(気温)**を 交絡(confounder) と呼びます。交絡があると、XXYY は因果関係がなくても相関します。

flowchart LR
  C["交絡 C(気温・重症度など)"] --> X["処置 X"]
  C --> Y["結果 Y"]
  X -.->|"本当に知りたい因果効果"| Y

XCYX \leftarrow C \rightarrow Y という経路(バックドアパス因果ダイアグラムとd分離 で厳密化)が開いていると、XXYY の相関には「本当の因果(XYX\to Y)」と「交絡由来の見せかけ(CC 経由)」が混ざります。素朴な相関・平均差はこの2つを区別できません。

識別の話を先に:観察データの平均差を因果効果と読むには「交絡がすべて観測され調整されている」といった仮定が要ります。どんな仮定なら因果と言えるかは 識別の仮定 で、調整すべき変数の選び方は バックドア基準と識別 で扱います。本ノートはまず「素朴な比較が壊れる」事実を体感します。

2. 交絡で符号が逆転する様子を擬似データで作る

シミュレーションの強みは、真の因果効果を自分で決められることです。ここでは処置 XX の真の効果を ATEtrue=+1.0\text{ATE}_\text{true}=+1.0 と仕込みます。一方で交絡 CC(重症度)は「重症ほど処置されやすく(CXC\to X)」「重症ほど結果が悪い(CYC\to Y)」という形で入れます。すると素朴な平均差はどうなるでしょうか。

import numpy as np
import pandas as pd

# === 交絡があると素朴な平均差が真の効果と逆符号になることを確かめる ===
rng = np.random.default_rng(42)
n = 20000

# 交絡 C(例:重症度): 0/1。半々で発生
C = rng.binomial(1, 0.5, size=n)

# 処置 X: C が高い(重症)ほど処置されやすい(C→X)
prob_treat = np.where(C == 1, 0.8, 0.2)
X = rng.binomial(1, prob_treat)

# 結果 Y: 真の処置効果は +1.0。ただし C は Y を 3 下げる(C→Y)
ATE_true = 1.0
Y = 2.0 + ATE_true * X - 3.0 * C + rng.normal(0, 1.0, size=n)

# 素朴な平均差(交絡を無視)
naive = Y[X == 1].mean() - Y[X == 0].mean()

# C で層別し、各層の効果を母集団の層比率で加重平均
effect_by_level = []
weight_by_level = []
for c in [0, 1]:
    in_level = C == c
    diff = Y[(X == 1) & in_level].mean() - Y[(X == 0) & in_level].mean()
    effect_by_level.append(diff)
    weight_by_level.append(in_level.mean())
adjusted = np.average(effect_by_level, weights=weight_by_level)

print(f"真の ATE            = {ATE_true:.3f}")
print(f"素朴な平均差         = {naive:.3f}")
print(f"C で層別・調整後     = {adjusted:.3f}")
print(f"層内効果: C=0 {effect_by_level[0]:.3f}, C=1 {effect_by_level[1]:.3f}")

出力:

真の ATE            = 1.000
素朴な平均差         = -0.787
C で層別・調整後     = 1.006
層内効果: C=0 0.986, C=1 1.025

出力の意味:真の効果は +1.0+1.0(処置は結果を良くする)なのに、素朴な平均差は 0.787-0.787 と負になりました。符号が逆転しています。理由は「処置を受けた群は重症(C=1C=1)が多く、重症はもともと結果が悪い」から。処置の良い効果が、重症であることの悪さに覆い隠されたのです。ところが C=0C=0C=1C=1層別して各層内で比べると、どちらも約 +1.0+1.0(0.986 と 1.025)。それを母集団比率で加重平均すると 1.006ATEtrue1.006\approx \text{ATE}_\text{true} に戻りました。交絡を調整すれば真値が見える——因果推論の出発点です。

3. シンプソンの逆説:部分集団と全体で符号が反対になる

第2節の現象が一番劇的に出るのが シンプソンの逆説(Simpson’s paradox) です。実在データで見ます。腎臓結石の治療 A(開腹手術)と B(経皮的腎砕石術)の回復率を比べた古典例(Charig ら 1986)です。

import pandas as pd

# === シンプソンの逆説:部分集団では A 優勢なのに全体では B 優勢 ===
# 腎臓結石の治療 A/B の回復データ(Charig 1986 の有名な実データ)
data = pd.DataFrame({
    "結石サイズ": ["小", "小", "大", "大"],
    "治療":       ["A", "B", "A", "B"],
    "回復":       [81, 234, 192, 55],
    "患者数":     [87, 270, 263, 80],
})
data["回復率"] = (data["回復"] / data["患者数"]).round(3)
print("【部分集団ごと】")
print(data.to_string(index=False))

# 治療ごとに小・大を合算した「全体」回復率
totals = data.groupby("治療")[["回復", "患者数"]].sum()
totals["全体回復率"] = (totals["回復"] / totals["患者数"]).round(3)
print("\n【全体(小+大を合算)】")
print(totals.to_string())

出力:

【部分集団ごと】
結石サイズ 治療  回復  患者数   回復率
    小  A  81   87 0.931
    小  B 234  270 0.867
    大  A 192  263 0.730
    大  B  55   80 0.688

【全体(小+大を合算)】
     回復  患者数  全体回復率
治療
A   273  350  0.780
B   289  350  0.826

出力の意味:結石が小さい場合は A(0.931)が B(0.867)に勝ち大きい場合も A(0.730)が B(0.688)に勝つ。どちらのサイズでも A が良いのに、全体で合算すると B(0.826)が A(0.780)を逆転します。種明かしは交絡=結石サイズです。難しい大結石には主に A(263 人)が、易しい小結石には主に B(270 人)が使われました。A は不利なケースを多く引き受けたため、合算すると見かけの回復率が下がるのです。

ここで重要なのは「どちらを信じるべきか」。結石サイズという交絡を**揃えて(層別して)**比べた部分集団の結論(A が良い)が因果的に正しく、合算した全体の比較は交絡に汚染されています。「データを足し合わせれば真実に近づく」は誤りで、揃えるべきものを揃えて初めて因果が見える——これが因果推論の核心的な教訓です。

4. 仮定の直観的意味:なぜ「揃える」と因果が見えるのか

層別が効いたのは、同じ CC の中では処置の割り当てが結果と無関係に近くなるからです。重症度 CC を固定すれば、その層の中での処置・非処置はおおむね「同じ条件の人を比べている」状態に近づきます。これを厳密にしたのが 条件付き交換可能性(conditional exchangeability)

{Y(1),Y(0)} ⁣ ⁣ ⁣XC\{Y(1),\,Y(0)\} \perp\!\!\!\perp X \mid C

で、「CC を与えれば、誰が処置されるかは潜在結果と独立」という仮定です(潜在結果モデル で潜在結果 Y(1),Y(0)Y(1),Y(0) を、識別の仮定 でこの仮定そのものを扱います)。この仮定が成り立つ CC をすべて調整できたときに限り、層別・調整した平均差を因果効果と読めます。逆に言えば、調整し損ねた交絡(未観測交絡)が残れば、いくら層別しても因果にはなりません。

⚠️ よくある誤解・落とし穴

関連ノート