論文一覧に戻る 📚 用語解説(ジャストインタイム型データサイエンス教育)
ランダム効果モデル
Random Effects Model (RE)
個体固有効果を「ランダム変数」として扱うパネルモデル。FE より仮定は強いが効率が良い。
パネル分析REREランダム効果random effects

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

変量効果モデル周辺の重要語をクイックアクセス:

変量切片モデル 変量傾きモデル ICC(級内相関) 分散成分 縮小推定(shrinkage) BLUP 過小収束 / Singular fit REML vs ML 変量と固定の選択 statsmodels MixedLM pymer4 / lme4 PyMC(ベイズ)

💡 30秒で分かる結論

🍰 まずはやさしく

個人のクセをまとめて扱う方法です。

効率よく分析するために使います。

都道府県ごとの違いを調べる時に便利です。

このモデルでできることを学びます。

random effects を 30 秒で把握する重要ポイント:

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

🍰 まずはやさしく

データの個性をランダムに扱う手法です。

地域の特性を分析するために使います。

47都道府県のデータを扱う時に役立ちます。

分析の手順と使い分けを読みましょう。

論文中に 「ランダム効果モデル」として登場する用語。

ランダム効果モデル とは:個体固有効果を「ランダム変数」として扱うパネルモデル。FE より仮定は強いが効率が良い。

本ページの主目的は「SSDSE-B-2026 の 47 都道府県 × 複数年パネルで個体効果を $\mu_i \sim N(0, \sigma_\mu^2)$ と仮定し、 時間不変変数の係数を残しつつ効率推定する」枠組みを示すことである。

後段では (1) RE / FE / Pooled OLS の比較、 (2) Hausman 検定で RE 妥当性を検証、 (3) statsmodels の MixedLM で実装し、 個体内・個体間分散の分解を確認する。

🎨 直感で掴む — ランダム効果モデル

🍰 まずはやさしく

個人のクセをバラつきとして捉える考え方です。

計算の手間を減らして分析するために使います。

クラスごとの成績の差をまとめるイメージです。

直感的な仕組みとメリットを解説します。

SSDSE-B-2026 で 47 都道府県 × 複数年のパネルを考えるとき、 「東京は他と違う」「沖縄は他と違う」というような 個体固有のクセ をどう扱うかが論点になります。 ランダム効果 (Random Effects, RE) モデルは、 この個体クセを 母集団からランダムに引かれた変量 と見なして、 47 個分のダミー変数を立てずに 分散 $\sigma_\mu^2$ を 1 つ推定 することで効率的に処理します。

比喩で言えば、 学校の生徒成績を分析するときに「クラス A」「クラス B」とダミーを大量に作る代わりに、 「クラスごとのバラつき」という 1 つの分散 でまとめてしまう発想です。 ダミーで自由度を消費しないため、 サンプルが少ない場合や時間不変変数(地域の気候など)の係数を推定したいときに重宝します。

固定効果モデル (FE) との分業も直感的に理解できます。 FE は「都道府県 47 個分のダミー変数」を入れて切片を個別推定、 RE は「個体差は確率変数」として分散 1 個だけ推定。 結果として、 FE は 説明変数と個体効果が相関していても OK な代わりに、 時間不変変数 (例: 海に面しているか否か) の係数は推定できなくなります。 RE は逆で、 時間不変変数の効果を推定できる代わりに、 直交性仮定が崩れるとバイアスが出ます。 SSDSE-B のように 47 都道府県 × 数年 の小規模パネルでは、 まず RE で推定して Hausman 検定で FE への切替を判断、 という順序が定番です。

具体的な使い所: 都道府県別の婚姻率と出生率のパネル分析。 沖縄や東京には固有の文化・出生行動パターンがあり、 これを 毎個体に切片を立てる と 47 自由度を消費。 RE で地域差 = N(0, σu²) の確率変数と仮定すれば、 自由度を温存しつつ婚姻率の係数を効率良く推定できます (σu² の値そのものが「地域による出生率のバラつき度」として政策的にも有用)。

📐 定義・数式

🍰 まずはやさしく

個体差を数式で表したモデルです。

正しく計算できる条件を確認するために使います。

地域の気候と結果の関係を調べる時に使えます。

数式を使った定義とルールを学びましょう。

$$ y_{it} = \alpha + \boldsymbol{x}_{it}^{\top}\boldsymbol{\beta} + u_i + \varepsilon_{it}, \quad u_i \sim \mathcal{N}(0, \sigma_u^2),\ \varepsilon_{it} \sim \mathcal{N}(0, \sigma_\varepsilon^2) $$

重要な仮定は $\operatorname{Cov}(u_i, \boldsymbol{x}_{it}) = 0$ — 個体固有効果と説明変数が無相関であること(直交性)。 これが満たされれば RE 推定量は BLUE となります。 SSDSE-B-2026 で婚姻率 $x$ と地域固有効果 $u_i$ が相関していそうなら、 RE の前提が崩れます(その場合は FE)。

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

記号意味SSDSE-B-2026 解釈
$u_i$個体ランダム効果(平均 0 の確率変数)「都道府県ごとの未観測の地域特性」を 1 つの分散で要約
$\sigma_u^2$個体間分散地域差の大きさ
$\sigma_\varepsilon^2$個体内(時間内)分散同じ都道府県内の年次変動
$\rho = \frac{\sigma_u^2}{\sigma_u^2 + \sigma_\varepsilon^2}$級内相関(ICC)同じ都道府県の観測がどれだけ似るか

推定は GLS(一般化最小二乗)。 OLS との違いは観測値を $1-\hat{\theta}$ だけ平均から引いた「部分組内変換」を行う点で、 FE(完全変換)と OLS(無変換)の中間に位置します。

📖 詳細な解説

この用語は、 統計データ解析・データサイエンスの世界で重要な概念の1つです。 ジャストインタイム型学習では、 必要なときに参照し、 関連概念と合わせて学ぶことで定着を図ります。

基本的な定義

この用語の基本的な意味、 数学的定義、 直感的理解について、 上記の3つの概念マップを通じて、 関連する用語と一緒に把握しましょう。

使い時の判断基準

Python による実装例

▼ コード解説(ランダム効果モデルの基本(statsmodels MixedLM))
🎯 解説: statsmodels の MixedLM で、 消費支出 L3221 を log(総人口)・log(65 歳以上人口) で説明し、 地方ブロック 8 群の切片のずれ u_j を確率変数 N(0, σ_u²) として推定する。 最後に ICC = σ_u² / (σ_u² + σ_ε²) を出す。
📥 入力例: SSDSE-B-2026 の全 564 行(47 都道府県 × 12 年度) L3221 消費支出(二人以上の世帯、 円/月), A1101 総人口, A1303 65 歳以上人口 群: 地域コード R01〜R47 から作った 8 地方ブロック(北海道は 1 道 × 12 年 = 12 行)
📤 実行例(実測) Mixed Linear Model Regression Results =================================================================== Model: MixedLM Dependent Variable: L3221 No. Observations: 564 Method: REML No. Groups: 8 Scale: 448765836.5261 Min. group size: 12 Log-Likelihood: -6399.5809 Max. group size: 108 Converged: Yes Mean group size: 70.5 ------------------------------------------------------------------- Coef. Std.Err. z P>|z| [0.025 0.975] ------------------------------------------------------------------- Intercept 226981.105 21293.053 10.660 0.000 185247.488 268714.722 log_pop -10698.133 8657.843 -1.236 0.217 -27667.193 6270.927 log_old 16205.165 9250.024 1.752 0.080 -1924.548 34334.878 Group Var 82621973.249 2290.059 =================================================================== ICC = 0.155
💬 読み方: ブロック間分散 Group Var は 8,262 万(標準偏差 約 9,090 円)、 残差分散 Scale は 4.49 億で、 ICC = 0.155。 消費支出のばらつきの 15.5% が地方ブロックの違いで説明できる。 固定効果は log_pop −10,698(p = 0.217)、 log_old +16,205(p = 0.080)でどちらも 5% では有意でなく、 人口と高齢人口は強く相関しているので係数の符号は分けて解釈しにくい。 なお同じ県の 12 年分を独立な観測として扱っているため、 標準誤差は小さめに出ている可能性がある。
 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
29
30
31
import numpy as np
import pandas as pd
import statsmodels.formula.api as smf

# 1行目=英字コード, 2行目=日本語名。コード行をヘッダにして日本語名行を捨てる
df = pd.read_csv('data/raw/SSDSE-B-2026.csv',
                 encoding='cp932', skiprows=[1])
# 年度列コードは 'SSDSE-B-2026'、地域コードは 'R01000' 形式
df['pref_no'] = df['Code'].str[1:3].astype(int)   # R01000 -> 1

def region(no):
    if no == 1:               return '北海道'
    if 2  <= no <= 7:         return '東北'
    if 8  <= no <= 14:        return '関東'
    if 15 <= no <= 23:        return '中部'
    if 24 <= no <= 30:        return '近畿'
    if 31 <= no <= 35:        return '中国'
    if 36 <= no <= 39:        return '四国'
    return '九州沖縄'

df['region']  = df['pref_no'].apply(region)
df['log_pop'] = np.log(df['A1101'])   # A1101 = 総人口
df['log_old'] = np.log(df['A1303'])   # A1303 = 65歳以上人口

# L3221=消費支出(二人以上の世帯) を総人口・高齢人口で説明、地方ブロックを変量効果に
md  = smf.mixedlm('L3221 ~ log_pop + log_old',
                  data=df, groups=df['region'])
res = md.fit(reml=True)
print(res.summary())
icc = res.cov_re.iloc[0, 0] / (res.cov_re.iloc[0, 0] + res.scale)
print(f'ICC = {icc:.3f}')

典型的な出力例: 固定効果 log_pop=−10698, log_old=+16205、 ブロック分散 σ_u²≈8.3×10⁷、 残差分散 σ_e²≈4.5×10⁸、 ICC≈0.155。 「ブロック間で消費支出水準に 16% 程度のばらつきがある」と読める。 ICC が 0.05 を下回るなら変量効果を入れるご利益はほぼ無く、 通常 OLS で十分。

BLUP(各ブロックの予測切片偏差)

▼ コード解説(BLUP(最良線形不偏予測量))
🎯 解説: 上のモデル res から、 各地方ブロックの切片のずれ u_j の予測値(BLUP)を取り出し、 小さい順に並べる。
📥 入力例: res.random_effects(8 ブロック分の辞書。 値は Group の 1 要素)
1
2
3
blup = res.random_effects
for r, s in sorted(blup.items(), key=lambda x: x[1].iloc[0]):
    print(f'{r:<6s}  BLUP切片偏差 = {s.iloc[0]:+.3f}')
📤 実行例(実測) 九州沖縄 BLUP切片偏差 = -10453.103 近畿 BLUP切片偏差 = -5962.727 北海道 BLUP切片偏差 = -5842.730 東北 BLUP切片偏差 = -5773.396 中国 BLUP切片偏差 = +1966.193 四国 BLUP切片偏差 = +2404.619 中部 BLUP切片偏差 = +9221.045 関東 BLUP切片偏差 = +14440.099

💬 BLUP は地方ブロックごとの消費支出の切片が全体平均からどれだけずれるかを表し、関東が +14,440 円で最も高く、九州沖縄が −10,453 円で最も低い。ブロック間の分散は約 8,262 万(標準偏差約 9,090 円)で、北海道は 1 県 12 年分しか観測が無いため、他のブロックより 0 の側へ強く縮められやすい。人口と高齢人口を調整した後でもこれだけ地域差が残ることが、変量効果を入れる理由になっている。

🧮 数式に値を入れて手で計算する: 級内相関 ICC

合成データで個体内分散 vs 個体間分散の比率を計算する。

Step 1: 分散分解

σ²_between = 4 (個体間分散) σ²_within = 6 (個体内分散) σ²_total = 10

Step 2: ICC

ICC = σ²_between / σ²_total = 4/10 = 0.40 40% が個体間差で説明 ランダム効果の重要性: ICC > 0.05 で必要

🐍 Python で再現

1
2
3
4
sigma_b = 4
sigma_w = 6
icc = sigma_b / (sigma_b + sigma_w)
print(f"ICC: {icc}")

📤 実行結果

ICC: 0.4

💬 手計算 (Step 2) 0.40 と Python 出力が完全一致。

🧮 実値で計算してみる — 7 地方ブロックの消費支出で ICC を出す

変量効果モデルの出発点は 「群で分けると、どれくらい説明がつくのか」 です。 それを 1 つの数にしたのが 級内相関係数 ICC。 SSDSE-B-2026(2023 年度・47 都道府県)の L3221 消費支出(二人以上の世帯) を、地域コードから作った 7 地方ブロックで分けて、 実際に手で計算します。

Step 1: 群ごとの人数・平均・標準偏差を出す

地方ブロック 県数 ni 平均(円) 標準偏差(円)
関東7316,508.921,607.9
中部9305,033.614,786.6
近畿7296,754.426,792.0
北海道東北7295,228.620,753.8
中国5292,150.412,932.4
九州沖縄8279,202.921,741.0
四国4276,528.235,878.8

全 47 県の平均は 295,856 円、1 群あたりの平均県数は $\bar{n} = 47 \div 7 = 6.714$ です。 関東(316,509 円)と四国(276,528 円)で 約 4 万円 の開きがあります。 この開きが「地方ブロックというまとまりの効果」なのか、 それとも「県ごとのばらつきがたまたまそう見えているだけ」なのかを、これから数で分けます。

Step 2: 群間の分散(MSB)と群内の分散(MSW)に分ける

群間:7 つの群平均が全体平均からどれだけ散らばっているかに、1 群あたりの県数を掛けます。

$$ \mathrm{MSB} = \bar{n} \cdot \mathrm{Var}(\bar{y}_1,\dots,\bar{y}_7) = 6.714 \times 1.939\times 10^{8} = 1.302 \times 10^{9} $$

群内:各群の中での分散を平均します。上の表の標準偏差を 2 乗して平均した値です。

$$ \mathrm{MSW} = \frac{1}{7}\sum_{i=1}^{7} s_i^2 = 5.373 \times 10^{8} $$

Step 3: ICC の式に入れる

$$ \mathrm{ICC} = \frac{\mathrm{MSB} - \mathrm{MSW}}{\mathrm{MSB} + (\bar{n}-1)\,\mathrm{MSW}} = \frac{1.302\times10^{9} - 5.373\times10^{8}}{1.302\times10^{9} + 5.714 \times 5.373\times10^{8}} $$ $$ = \frac{7.646\times10^{8}}{4.372\times10^{9}} = \mathbf{0.175} $$

Step 4: 読み方

ICC = 0.175。消費支出のばらつきのうち、地方ブロックの違いで説明できるのは 約 18% にすぎず、残りの 約 82% は同じ地方の中での県ごとの差です。 一元配置分散分析でも F = 2.605、p = 0.032 と、有意ではあるものの効果は大きくありません。 つまり「同じ地方だから消費支出も似ている」とは、あまり言えないということです。

この 0.175 という値が、変量効果モデルを使うかどうかの判断材料になります。 ICC がほぼ 0 なら群を無視した単純な回帰で十分、 0.5 を超えるようなら群の効果が支配的で、群ごとの切片を推定する意味が大きい。 0.175 はその中間で、「群を入れても損はないが、劇的には変わらない」という領域です。

Step 5: 同じ計算を Python で再現する

このコードでやること:上の Step 1〜3 をそのまま numpy/scipy で計算し、 手計算と一致することを確かめます。あわせて statsmodels の混合効果モデルでも 同じ量を推定し、2 つの推定方法で値がどう違うかを見ます。

📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行) 都道府県 L3221(消費支出(二人以上の世帯)) 北海道 296,888 東京都 341,320 沖縄県 251,222 …(全 47 行)
 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
29
30
31
# ── この抜粋で使うデータを用意します ──
import numpy as np
import pandas as pd
from scipy import stats

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023].copy()      # 2023 年の 47 都道府県
_no = df['Code'].str[1:3].astype(int)           # R13000 → 13
df['region'] = np.select(
    [_no <= 7, _no <= 14, _no <= 23, _no <= 30, _no <= 35, _no <= 39],
    ['北海道東北', '関東', '中部', '近畿', '中国', '四国'], default='九州沖縄')
df['y'] = df['L3221'].astype(float)             # 消費支出(二人以上の世帯)

# Step 1: 群ごとの県数・平均・標準偏差
print(df.groupby('region')['y'].agg(['size', 'mean', 'std']).round(1))
print('全国平均 =', round(df['y'].mean(), 1))

# Step 2: MSB と MSW
groups = [v.values for _, v in df.groupby('region')['y']]
n_bar = df.groupby('region').size().mean()
msb = np.var([g.mean() for g in groups], ddof=1) * n_bar
msw = np.mean([np.var(g, ddof=1) for g in groups])
print(f'n_bar = {n_bar:.3f}, MSB = {msb:.4g}, MSW = {msw:.4g}')

# Step 3: ICC
icc = (msb - msw) / (msb + (n_bar - 1) * msw)
print(f'ICC = {icc:.3f}')

# Step 4: 一元配置分散分析でも確かめる
F, p = stats.f_oneway(*groups)
print(f'F = {F:.3f}, p = {p:.4f}')

📤 実行すると次の出力が得られる:

size mean std region 中国 5 292150.4 12932.4 中部 9 305033.6 14786.6 九州沖縄 8 279202.9 21741.0 北海道東北 7 295228.6 20753.8 四国 4 276528.2 35878.8 近畿 7 296754.4 26792.0 関東 7 316508.9 21607.9 全国平均 = 295856.0 n_bar = 6.714, MSB = 1.302e+09, MSW = 5.373e+08 ICC = 0.175 F = 2.605, p = 0.0317

💬 一致の確認:Step 1 の表、Step 2 の MSB = 1.302×10⁹ / MSW = 5.373×10⁸、Step 3 の ICC = 0.175 が、手計算とそのまま一致しました。分散分析の F = 2.605、p = 0.032 も Step 4 の記述どおりです。ICC は「群で分けたときの説明力」を 0〜1 で表すので、0.175 = 地方ブロックで説明できるのは 2 割弱、と読みます。

🐍 Python 実装バリエーション — statsmodels / pymer4 / PyMC

1. statsmodels.formula.api.mixedlm(標準・REML)

▼ コード解説(変量切片モデルと変量傾きモデル(statsmodels mixedlm))
🎯 解説: 2023 年度 47 県の消費支出を総人口(万人)と高齢化率で説明し、 7 地方ブロックの切片だけがずれる変量切片モデル m1 と、 総人口の傾きもブロックごとに変わる変量傾きモデル m2(re_formula='~x1')を当てはめて比べる。
📥 入力例: SSDSE-B-2026 の 2023 年度 47 行 y = L3221 消費支出(円/月), x1 = A1101 総人口(万人), x2 = 高齢化率(A1303/A1101×100, %) 群: 7 地方ブロック(北海道は東北とまとめる)
📤 実行例(実測) Mixed Linear Model Regression Results =================================================================== Model: MixedLM Dependent Variable: y No. Observations: 47 Method: REML No. Groups: 7 Scale: 493016843.2846 Min. group size: 4 Log-Likelihood: -516.5683 Max. group size: 9 Converged: Yes Mean group size: 6.7 ------------------------------------------------------------------- Coef. Std.Err. z P>|z| [0.025 0.975] ------------------------------------------------------------------- Intercept 323559.765 49779.683 6.500 0.000 225993.379 421126.151 x1 14.877 18.086 0.823 0.411 -20.570 50.324 x2 -1011.952 1466.296 -0.690 0.490 -3885.840 1861.936 Group Var 55713364.476 4148.007 =================================================================== Mixed Linear Model Regression Results ========================================================================= Model: MixedLM Dependent Variable: y No. Observations: 47 Method: REML No. Groups: 7 Scale: 416382622.7897 Min. group size: 4 Log-Likelihood: -517.8791 Max. group size: 9 Converged: No Mean group size: 6.7 ------------------------------------------------------------------------- Coef. Std.Err. z P>|z| [0.025 0.975] ------------------------------------------------------------------------- Intercept 309064.680 48423.291 6.383 0.000 214156.772 403972.587 x1 22.413 34.258 0.654 0.513 -44.731 89.557 x2 -586.543 1410.804 -0.416 0.678 -3351.669 2178.583 Group Var 395843767.461 Group x x1 Cov -1398055.548 x1 Var 6365.287 =========================================================================
💬 読み方: m1 は収束し、 ブロック間分散 5,571 万に対し残差分散 4.93 億で、 ICC に直すと約 0.10。 x1 は 1 万人あたり +14.9 円(p = 0.411)、 x2 は高齢化率 1 ポイントあたり −1,012 円(p = 0.490)で、 どちらも有意ではない。 m2 は Converged: No のままで、 群が 7 つしかない中で切片と傾きの分散・共分散を推定しようとして不安定になっている。 総人口を人単位のまま入れると m1 も収束しなくなるので、 説明変数は万人などに桁をそろえる。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# ── この抜粋で使うデータを用意します ──
import numpy as np
import pandas as pd
import statsmodels.formula.api as smf

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.copy()
_no = df['Code'].str[1:3].astype(int)
df['region'] = np.select(
    [_no <= 7, _no <= 14, _no <= 23, _no <= 30, _no <= 35, _no <= 39],
    ['北海道東北', '関東', '中部', '近畿', '中国', '四国'], default='九州沖縄')
df['y'] = df['L3221'].astype(float)     # 消費支出
df['x1'] = df['A1101'].astype(float) / 1e4   # 総人口(万人)。人単位のままだと最適化が収束しない
df['x2'] = df['A1303'] / df['A1101'] * 100   # 高齢化率

m1 = smf.mixedlm('y ~ x1 + x2', df, groups=df['region']).fit(reml=True)
m2 = smf.mixedlm('y ~ x1 + x2', df, groups=df['region'],
                 re_formula='~x1').fit(reml=True)
print(m1.summary()); print(m2.summary())

2. pymer4 — R の lme4 を Python から呼ぶ

R の lme4 と等価のインターフェースで、 p値が Satterthwaite 近似で出る。 学術論文で lme4 を再現したい場合に便利。

▼ コード解説(pymer4(R の lme4)で変量切片モデル)
🎯 解説: pymer4 の Lmer で、 上の m1 と同じ y ~ x1 + x2 + (1|region) を R の lme4 に当てはめさせ、 summary と固定効果 fixef を表示する。
📥 入力例: 上のブロックで作った df(2023 年度 47 行、 y / x1(万人)/ x2 / region)
📤 実行例: R と pymer4 のインストールが必要なため、 このページでは実行していない(実測ではない)。
💬 読み方: lme4 の REML は statsmodels の m1 と同じ量を推定するので、 固定効果は切片 約 323,560・x1 約 14.9・x2 約 −1,012 に近い値になるはず。 実行したら m1 の表と照らし合わせ、 大きく違えば群の作り方や変数の単位が同じかを確かめる。
1
2
3
4
from pymer4.models import Lmer
m = Lmer('y ~ x1 + x2 + (1|region)', data=df).fit()
print(m.summary())
print(m.fixef)

3. PyMC でベイズ階層モデル

▼ コード解説(PyMC でベイズ階層モデル)
🎯 解説: PyMC で、 7 地方ブロックの切片 a_j ~ N(mu_a, sigma_a) を持つ階層モデルを MCMC(NUTS, 4 チェーン × 2,000 draw)で推定する。 y・x1・x2 は標準化してから当てはめ、 切片は非中心化で書く。
📥 入力例: 上のブロックで作った df(2023 年度 47 行、 y / x1 / x2 / region)
📤 実行例(実測) mean sd eti89_lb eti89_ub ess_bulk ess_tail r_hat mcse_mean mcse_sd mu_a -0.015 0.21 -0.35 0.3 3335 3476 1.00 0.0039 0.0043 sigma_a 0.35 0.245 0.039 0.79 2014 2431 1.00 0.0052 0.0036 b1 0.168 0.203 -0.16 0.49 4582 5170 1.00 0.003 0.0021 b2 -0.135 0.201 -0.45 0.18 4664 5375 1.00 0.0029 0.0021 sigma 0.944 0.106 0.79 1.1 7230 5878 1.00 0.0013 0.0012
💬 読み方: すべて標準化した単位で、 ブロックの切片のばらつき sigma_a の事後平均は 0.35(89% 区間 0.04〜0.79)、 残差 sigma は 0.94。 sigma_a² / (sigma_a² + sigma²) は約 0.12 で、 statsmodels の m1 の ICC 約 0.10 と近い。 b1(総人口)0.17・b2(高齢化率)−0.13 はどちらも区間が 0 をまたぐ。 r_hat はすべて 1.00、 ess も 2,000 以上で、 乱数によって小数第 2〜3 位は実行ごとに少し変わる。 群が 7 つしかないと sigma_a の区間は広く、 事前分布の置き方で結果が動きやすい。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import pymc as pm
# y(消費支出)は 30 万円前後、x1(総人口)は数十万〜1,400 万人と桁が大きく、
# このままでは下の事前分布(標準偏差 1)と合わないので、3 変数とも標準化してから当てはめる
z = lambda s: ((s - s.mean()) / s.std()).values
y_z, x1_z, x2_z = z(df['y']), z(df['x1']), z(df['x2'])
region_idx, regions = pd.factorize(df['region'])
with pm.Model() as model:
    mu_a    = pm.Normal('mu_a', 0, 1)
    sigma_a = pm.HalfNormal('sigma_a', 1)
    # 非中心化: 群が 7 つしかないと a ~ N(mu_a, sigma_a) のままでは発散が多発するので、
    # 標準正規の a_raw を sigma_a 倍して足す形に書き換える
    a_raw   = pm.Normal('a_raw', 0, 1, shape=len(regions))
    a       = pm.Deterministic('a', mu_a + sigma_a * a_raw)
    b1      = pm.Normal('b1', 0, 1)
    b2      = pm.Normal('b2', 0, 1)
    sigma   = pm.HalfNormal('sigma', 1)
    mu      = a[region_idx] + b1*x1_z + b2*x2_z
    y_obs   = pm.Normal('y_obs', mu, sigma, observed=y_z)
    trace   = pm.sample(2000, tune=1000, chains=4, target_accept=0.95, random_seed=0)
print(pm.summary(trace, var_names=['mu_a', 'sigma_a', 'b1', 'b2', 'sigma']).round(3))

4. scipy で ICC を素朴に計算する

▼ コード解説(scipy で ICC を素朴に計算する)
🎯 解説: scipy の一元配置分散分析と、 平均平方 MSB・MSW から ICC(1,1) = (MSB − MSW) / (MSB + (n̄ − 1)MSW) を計算する。
📥 入力例: SSDSE-B-2026 の 2023 年度 47 行、 y = L3221 消費支出(円/月) 群: 7 地方ブロック(北海道は 1 道だけで群内分散が出ないので東北とまとめる)
📤 実行例(実測) 各群の県数 = {'中国': 5, '中部': 9, '九州沖縄': 8, '北海道・東北': 7, '四国': 4, '近畿': 7, '関東': 7} F = 2.605, p = 0.0317 ICC(1,1) = 0.175
💬 読み方: 群の大きさは四国の 4 県から中部の 9 県まで。 F = 2.605(p = 0.0317)で地方ブロック間の平均差は 5% 水準で有意だが、 ICC は 0.175 で、 消費支出のばらつきのうちブロックで説明できるのは 2 割弱にとどまる。 上の「実値で計算してみる」の手計算と同じ値になる。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# ── この抜粋で使うデータを用意します(地方ブロックを群とする)──
import numpy as np
import pandas as pd
from scipy import stats

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023].copy()
_no = df['Code'].str[1:3].astype(int)
# 北海道は 1 県だけで群内分散が定義できず ICC が nan になるので、東北とまとめる
df['region'] = np.select(
    [_no <= 7, _no <= 14, _no <= 23, _no <= 30, _no <= 35, _no <= 39],
    ['北海道・東北', '関東', '中部', '近畿', '中国', '四国'], default='九州沖縄')
df['y'] = df['L3221']       # 消費支出を観測値にする

groups = [df.loc[df.region==r, 'y'].values for r in df['region'].unique()]
F, p = stats.f_oneway(*groups)
n = df.groupby('region').size().mean()
msb = np.var([g.mean() for g in groups], ddof=1) * n
msw = np.mean([np.var(g, ddof=1) for g in groups])
icc = (msb - msw) / (msb + (n-1)*msw)
print(f'各群の県数 = {df.groupby("region").size().to_dict()}')
print(f'F = {F:.3f}, p = {p:.4f}')
print(f'ICC(1,1) = {icc:.3f}')

🎮 触って理解する — 部分プーリング(縮小推定)

変量効果モデルの核心は、 各グループ(個体)の推定値を 「完全プーリング(全体平均)」 と 「プーリングなし(各群の生の平均)」 の 間 に縮小(shrinkage)させる点にあります。 縮小の度合いは、 グループ間分散 $\tau^2$ とグループ内誤差分散 $\sigma^2$、 そして 各群のデータ数 $n_i$ で決まります。 スライダーを動かして、 データが少ない群ほど全体平均へ強く引き寄せられること、 $\tau^2$ を大きくすると縮小が弱まることを体感してください。

大きい → 群ごとの個性を信じる → 縮小が弱い(プーリングなしに近い)
大きい → 各群の平均が当てにならない → 縮小が強い(全体平均に近い)
情報量の比 τ²/σ² = 0.250 / 全体平均(完全プーリング) μ = 58.8
○ 生の群平均(プーリングなし) ● 縮小後の推定値(部分プーリング) ┊ 全体平均 μ(完全プーリング)

💡 縮小係数の式: 群 $i$ の推定値は $\hat\theta_i = \lambda_i\,\bar y_i + (1-\lambda_i)\,\mu$、 ただし縮小の重み $\lambda_i = \dfrac{\tau^2}{\tau^2 + \sigma^2/n_i}$。 $n_i$ が小さいと $\sigma^2/n_i$ が大きくなり $\lambda_i$ が 0 に近づく(=全体平均へ強く縮小)。 $\tau^2$ を大きくすると $\lambda_i$ が 1 に近づく(=各群の生の平均を尊重)。 これが「情報を借りる(borrowing strength)」の正体です。

🧭 直感 — なぜ「確率変数とみなす」と縮小が起きるのか

固定効果モデルは各個体の切片を 独立なパラメータ として別々に推定するため、 データ 1〜2 点しかない群でもその生の平均をそのまま使います(過剰適合しやすい)。 一方 変量効果モデルは、 個体効果 $u_i$ が 共通の分布 $N(0,\tau^2)$ から抽出された と仮定します。 すると「他の群の情報」が事前分布を通じて各群に流れ込み、 データが乏しい群ほど全体平均という『みんなの知恵』を多めに借りる — これが部分プーリングであり、 James–Stein 推定量や経験ベイズ(BLUP)と同じ縮小の原理です。 縮小は個別群では多少バイアスを生みますが、 全体の予測二乗誤差はしばしば小さくなります。

⚠️ よくある落とし穴

🚀 発展

⚠️ 変量効果モデルの落とし穴 — 実務で必ず踏む 6 つ

① グループ数が少なすぎて分散成分が推定できない

変量効果に指定したグループの水準数が 5 未満だと、 群間分散 σ_u² の推定が不安定になり、 Singular fit(分散がほぼゼロに収束)が起きる。 SSDSE のように 8 ブロックでも厳しく、 6 ブロック以下なら基本的に変量効果として扱わず、 固定効果(ダミー変数)にした方が良い。 経験則として「変量効果のためには水準数 ≥ 5、 望ましくは ≥ 10」が目安とされる(Gelman & Hill, 2007)。 これを知らずに 3 群で REML を回すと、 信頼区間がほぼ無意味になる。

② 「変量効果 = 完全にランダム」と誤解する

「変量効果」と書かれるからといって、 各群の効果が完全に独立にサンプリングされるわけではない。 実際には「群効果が共通の正規分布 N(0, σ_u²) から抽出された」という階層的仮定を置いており、 群間の縮小(shrinkage)が暗黙的に働く。 そのため極端なサンプル数の群(n=1 や n=2)の推定値は集団平均に強く引き寄せられる。 これを「BLUP の縮小」と呼び、 古典 OLS の群ダミーとは予測値が大きく変わる。 縮小は予測誤差を下げるが、 個別群の効果を強調したい記述目的には不向き。

③ REML と ML の使い分けを意識しない

分散成分推定では REML(制限付き最尤)が ML より不偏に近く既定で推奨されるが、 固定効果の構造を尤度比検定で比較するときは ML に切り替える必要がある。 REML 同士の尤度は固定効果の構造を変えると単純比較できないからである。 statsmodels の MixedLM.fit() は既定 reml=True、 lme4 の lmer も既定 REML=TRUE。 AIC/BIC でモデル選択するときは特に注意する。 一方、 分散成分の有意性検定は REML のままで尤度比検定を実施するのが定石。

④ Singular fit を無視して結論を出す

変量傾きを入れると分散共分散行列が半正定値の境界に張り付き、 「σ_slope ≈ 0」「相関 ±1」となる Singular fit が頻発する。 これは「データから変量傾きを支持する情報がない」シグナルで、 モデルを変量切片のみに簡略化するか、 ベイズ事前分布を使った正則化(rstanarm, brms, PyMC)に切り替えるべき。 警告を無視して結果を読むと SE が過大評価され、 固定効果の検定がおかしくなる。 lme4 では isSingular() で診断可能。

⑤ 自由度・p値の計算法が実装でバラバラ

混合モデルでは「自由度をどう数えるか」が未解決問題で、 R の lme4 はあえて p 値を出さない。 一方、 lmerTest は Satterthwaite 近似、 SAS は Kenward-Roger、 statsmodels は Wald 検定で済ます。 同じデータでも実装によって p 値が 0.04 / 0.06 と境界を跨ぐことがある。 論文では「どの近似を使ったか」を必ず明記する。 ベストプラクティスはブートストラップによる信頼区間、 もしくはベイズ事後信用区間で報告すること。

⑥ 「Fixed vs Random」を経済学とは逆に覚える

統計学の「変量効果モデル」と、 経済学の「固定効果 vs 変量効果」の用語は概念が微妙に違う。 経済学で言う「固定効果」は群ダミー、 「変量効果」は群が誤差項と無相関と仮定したモデルで、 Hausman 検定で選ぶ。 統計学では「変量効果=階層モデルの上位レベル」と呼ぶ。 論文間を読み比べるときに混乱しないよう、 用語の出典分野を確認する習慣をつける。 SSDSE をパネル化して扱う際は経済学流の用法に従う方が論文と整合する。

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

変量効果モデル 前提: 線形回帰 / 混合モデル 並列: 固定効果モデル 発展: 階層ベイズ 応用: パネルデータ分析 推定: REML / ML 対比: OLS

Q1: 何を知りたい?

Q2: データの種類は?

Q3: サンプルサイズは?

Q4: 仮定は?

📏 効果量の参照表

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

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

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

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

📍 体系階層のパス

🌐 統計・データサイエンス › 因果推論 › パネル分析 › ランダム効果モデル

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

中心に ランダム効果モデル を置き、 そこから パネルデータ・固定効果・時系列分析 計 3 個の用語へ、 前提・兄弟・発展形といった関係を矢印で結んでいます。 線がどちら向きかを見れば、 先に読むべき用語とあとから読む用語が分かります。 ノードはドラッグで動かせ、 ホイールでズーム、 クリックでその用語のページへ遷移します。

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

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

大きな円が小さな円を包含する Circle Packing 図。 「ランダム効果モデル」は緑色でハイライト。

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

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

長方形を入れ子に分割した Treemap 図。 各分野の規模感を面積で比較。 「ランダム効果モデル」は緑色でハイライト。

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

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

💡 3 つの図は同じ位置関係を別の角度から描いています。 関係マップは ランダム効果モデル の隣に何が並ぶかを、 包含マップとツリーマップは 統計・データサイエンス → パネル分析 → ランダム効果モデル という入れ子の位置を示します。 「パネル分析には他に何があったか」を思い出したいときは包含マップを、 「次に何を読むか」を決めたいときは関係マップを開いてください。

🔗 隣接手法への橋渡し

「ランダム効果モデル」は単独で完結する手法ではなく、 隣接領域と連携することで真価を発揮する。

SSDSE-B-2026 を題材にしたランダム効果モデルの活用は、 上流 (パネル整形・ICC 算出) と下流 (BLUP 抽出・Hausman 検定) を含めて初めて完結する。

🌳 手法選択フロー

SSDSE-B-2026 のような都道府県パネルで random effects を選ぶ判断は、 (1) グループ数 J が十分大きいか (J ≥ 20 推奨、 47 都道府県は OK)、 (2) 県固有効果と説明変数の相関の有無、 (3) 県別効果に推論したいかで決まる。

Step 1: ICC = $\sigma_u^2 / (\sigma_u^2 + \sigma_e^2)$ が 0.1 以上 → 階層構造あり。 Step 2: Hausman 検定 p > 0.05 → random effects 採択 (固定効果と一致)。 Step 3: p < 0.05 → 県効果と説明変数に相関、 固定効果モデルに切替。

random effects を含む手法選択は、 データの性質・分析目的・運用制約の 3 軸で決まる。 シナリオ別 (大規模 / 外れ値多 / 解釈性重視 / 精度最優先 / 小データ / リアルタイム) に対応する手法の組合せを判断する。 選んだ後は「前処理確認 / ハイパラ調整 / 性能評価 / 頑健性チェック / 解釈」の 5 ステップで検証することが、 結果の信頼性確保に不可欠。

🧭 さらに深掘り — 部分プーリング・収縮・変量効果の外生性

既存の 🎨直感・🎮ウィジェット・⚠️落とし穴 を踏まえ、 ここでは「なぜ確率変数とみなすと得なのか」「どこで壊れるのか」を SSDSE-B-2026 の実測 ICC と結びつけて一段深く整理します。 数式は上の 部分プーリングのウィジェット の縮小係数 $\lambda_i = \tau^2/(\tau^2+\sigma^2/n_i)$ をそのまま使います。

① 直感 — 固定 → 変量は「切片の本数」を連続的に選ぶダイヤル

同じパネルに対する 3 つの立場は、 実は「各グループにどれだけ独立な切片を許すか」という 1 本のダイヤルの目盛です。 プール OLS(完全プーリング)は切片 1 本を全県で共有し、 固定効果(無プーリング)は 47 本の切片を独立パラメータとして別々に推定します。 変量効果はその 中間で、 「47 本の切片が共通の分布 $u_i\sim N(0,\tau^2)$ から生まれた」と仮定し、 実効的な切片の自由度を $\tau^2$ の大小に応じて 1 本〜47 本の間で データに決めさせます。 $\tau^2\to0$ で完全プーリング、 $\tau^2\to\infty$ で無プーリングに一致する — この両極を内包する点が「確率変数とみなす」ことのご利益です。

縮小(shrinkage)が起きるのは、 各県の推定切片が「その県の生平均」と「全体平均」の重み付き平均になるからです。 重み $\lambda_i$ が観測数 $n_i$ に依存するため、 情報の乏しい県ほど全体平均という『みんなの知恵』を多く借ります(borrowing strength)。 これは ベイズの経験ベイズ推定・James–Stein 推定量と同じ原理で、 個別県では多少バイアスを負う代わりに全体の予測二乗誤差を下げます。

② 実測 ICC で「階層構造の強さ」を測る(SSDSE-B-2026)

級内相関 ICC $=\tau^2/(\tau^2+\sigma^2)$ は「同じ県の観測どうしがどれだけ似るか=グループ差が全分散に占める割合」です。 下表は SSDSE-B-2026(47 都道府県 × 12 年 = 564 行、 2012–2023)を県でグループ化し、 一元配置ランダム効果の ICC(1) を実測したものです(バランス型 $n=12$)。

変数(列コード)実測 ICC読み方
総人口(A1101)0.9995水準変数。 ほぼ全分散が県差 → 階層構造が支配的
65歳以上人口(A1303)0.9931同上。 年内変動はごくわずか
消費支出・二人以上世帯(L3221)0.6639県差は依然大きいが、 年次変動の余地もある

💡 ICC 解釈の落とし穴: 人口・高齢者数のような 水準(レベル)変数 は県間で桁が違うため ICC がほぼ 1.00 に張り付き、 「階層構造がある」という情報以上のことは言えません。 むしろ ICC が中程度(消費支出の 0.66)の変数の方が、 変量効果の縮小が実際に効き、 分析上おもしろい対象です。 ICC が 0.05 未満なら変量効果を入れるご利益はほぼ無く プール OLS で十分、 という目安も併せて覚えてください。

③ 収縮の強さは「グループのサンプルサイズ」で決まる

縮小係数を ICC $\rho$ と観測数 $n$ で書き直すと $\lambda = \dfrac{n\rho}{n\rho+(1-\rho)}$ となり、 $n$ が大きいほど 1 に近づく=生平均を尊重、 $n$ が小さいほど 0 に近づく=全体平均へ強く収縮します。 消費支出の実測 ICC $\rho=0.664$ で計算すると:

つまり SSDSE-B のように全県で年数がそろった バランス型パネルでは収縮量が均一になり、 部分プーリングの威力は控えめです。 縮小が劇的に効くのは、 一部の県で欠測が多い アンバランス型や、 グループあたりの標本が少ない調査データのとき。 「小さい県ほど強く引き寄せられる」現象を体感したい場合は、 上の ウィジェットで群ごとの $n$ を見比べてください。

④ 落とし穴(重要)— 変量効果の外生性が破れるとバイアス

変量効果推定量が BLUE になる前提は、 個体効果と説明変数の無相関 $\operatorname{Cov}(u_i,\boldsymbol{x}_{it})=0$(外生性・直交性)です。 これは 外生性の一種であり、 破れると 内生性によってバイアスが生じます。 SSDSE-B で典型的に危ういのは「所得の高い県ほど、 未観測の産業構造や都市化度(=$u_i$)も高い」といった相関で、 このとき消費や物価の係数が歪みます。

⑤ 発展 — 変量傾き・階層/マルチレベル・経験ベイズ

📝 補足(この深掘りセクションの数値の出所): 表の ICC 3 値は SSDSE-B-2026.csv(cp932, skiprows=[1])の 47 都道府県 × 12 年パネルを県でグループ化し、 一元配置ランダム効果 ICC(1)=$(MSB-MSW)/(MSB+(n-1)MSW)$ で実測した値です。 ③の $\lambda$ は実測 ICC=0.664 から $\lambda=n\rho/(n\rho+1-\rho)$ で算出。 $n=2,1$ のケースは SSDSE には存在しない架空の欠測状況を仮定した説明用の値です。