Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

都道府県ごとの集計データの扱い

都道府県ごとの合計データを処置変数と結果変数に使う場合

  • 人口が交絡している

  • 係数の解釈のため、1人あたりの値にして標準化したい

とい理由から、人口で割ったほうがいい

割ることが交絡のコントロールになる理由

欠落変数バイアス

  • long model: y=αp+βx+εy = \alpha p + \beta x + \varepsilon

  • short model: y=βx+εy = \beta x + \varepsilon

ppxxにも影響を与えているとする

p=γ0+γ1x+ϵp = \gamma_0 + \gamma_1 x + \epsilonとおいてlong modelに代入すると

y=α(γ0+γ1x+ϵ)+βx=α(γ0+ϵ)+(αγ1+β)xy = \alpha (\gamma_0 + \gamma_1 x + \epsilon) + \beta x\\ = \alpha (\gamma_0 + \epsilon) + (\alpha \gamma_1 + \beta) x\\

割ることがコントロールになるのはなぜか

y=αp+βx+εy = \alpha p + \beta x + \varepsilon

yp=αp+βx+εp=α+βxp+εp\frac{y}{p} = \frac{\alpha p + \beta x + \varepsilon}{p}\\ = \alpha + \beta \frac{x}{p} + \frac{\varepsilon}{p}

シミュレーション

データ生成過程を次のように、x,yx, yともに人口ppからの影響を受けると想定する。

x=αxpy=αyp+βx\begin{align} x &= \alpha_x p\\ y &= \alpha_y p + \beta x \end{align}

xyx\to yの効果であるβ\betaを推定したい

yとxをpで割った変換後の変数は次のようになる

yp=αyp+βxp=αy+βxp\frac{y}{p}= \frac{\alpha_y p + \beta x}{p} = \alpha_y + \beta \frac{x}{p}

なので、β\betaを推定するためにはyp\dfrac{y}{p}xp\dfrac{x}{p}に回帰させる必要がある

もしそのままyxy \sim xにすると

y=αyp+βxy=αyp+βαxpy=(αy+βαx)p\begin{align} y &= \alpha_y p + \beta x\\ &\to y = \alpha_y p + \beta \alpha_x p\\ &\to y = (\alpha_y + \beta \alpha_x) p\\ \end{align}

もしyp\dfrac{y}{p}をそのままのxxに回帰させると

yp=αyp+β(αxp)=(αy+βαx)p\begin{align} \frac{y}{p} &= \alpha_y p + \beta (\alpha_x p)\\ &= (\alpha_y + \beta \alpha_x) p\\ \end{align}

となってαy\alpha_yのぶんがバイアスに

import numpy as np
import pandas as pd

np.random.seed(0)
n = 1000
populations = np.random.lognormal(mean=10, size=n).astype(int)
alpha_x = 10
alpha_y = 5
beta = 3
x = alpha_x * populations + np.random.normal(scale=1000, size=n)
y = alpha_y * populations + beta * x + np.random.normal(scale=1000, size=n)  # xとyは微弱な相関
df = pd.DataFrame(dict(y=y, x=x, population=populations)).sort_values("population").assign(
    # 人口あたりのy, xを計算する
    ypp = lambda self: self.y / self.population,
    xpp = lambda self: self.x / self.population,
)
df
Loading...

yppとxppの相関が弱いことから、 xとyの相関はpopulationによる交絡の影響を受けていることがわかる

import matplotlib.pyplot as plt
fix, axes = plt.subplots(ncols=4, figsize=[20, 3])
df.plot.scatter(x="x", y="y", ax=axes[0])
df.plot.scatter(x="population", y="y", ax=axes[1])
df.plot.scatter(x="x", y="ypp", ax=axes[2])  # 線形性が満たされないのでそれによるバイアスが入りそう
df.plot.scatter(x="xpp", y="ypp", ax=axes[3])
<Figure size 2000x300 with 4 Axes>

しかし、可能ならypp ~ xppよりもy ~ x + populationのほうが良い気がする

import statsmodels.formula.api as smf
from stargazer.stargazer import Stargazer

Stargazer([
    smf.ols("y ~ x", data=df).fit(),
    smf.ols("y ~ x + population", data=df).fit(),
    smf.ols("ypp ~ x", data=df).fit(),
    smf.ols("ypp ~ xpp", data=df).fit(),
])
Loading...