論文一覧に戻る 📚 用語解説(ジャストインタイム型データサイエンス教育)
パネルデータ
Panel Data
同じ対象(個体)を複数時点で観測したデータ。クロスセクション+時系列の構造。
パネル分析panel data縦断データ

🔖 キーワード索引(補強・追加分)

パネルデータ 関連の補強キーワード。 クリックで該当箇所へ:

固定効果 変量効果 Hausman検定 差分の差(DID) クラスタ標準誤差 Within変換 時間固定効果 Driscoll-Kraay Mundlak Arellano-Bond

💡 30秒で分かる結論

🍰 まずはやさしく

同じ人を追いかける日記のようなデータです。

原因と結果の関係を正しく知るために使います。

県ごとの出生率の変化を調べる時に便利です。

このデータの重要ポイントを短く解説します。

panel data を 30 秒で把握する重要ポイント:

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

🍰 まずはやさしく

複数の視点からまとめた用語集のページです。

データの扱い方を正しく学ぶために使います。

都道府県のデータを使った分析に役立ちます。

定義から注意点までを順番に説明します。

論文中に 「パネルデータ」として登場する用語。

パネルデータ とは:同じ対象(個体)を複数時点で観測したデータ。クロスセクション+時系列の構造。

本ページでは「panel data」を扱う。 統計データ分析コンペティション (2026) の教材で、 SSDSE-B-2026 (47 都道府県 × 複数年 × 100 超列) の実データを使った再現可能な学習を目指す。

「panel data」は統計・データサイエンスの体系における重要概念のひとつ。 本ページは「定義・直感・数式・実装・落とし穴・関連手法」の 6 視点で構成され、 各視点は独立して読めるが順序通り読むと体系的な理解が得られる。

🎨 直感で掴む — パネルデータの正体

🍰 まずはやさしく

横の比較と縦の比較を合わせたものです。

変化の理由がどこにあるかを探るために使います。

同じ生徒の身長を毎年測るイメージです。

データの仕組みを直感的に理解しましょう。

パネルデータは クロスセクション(横断面)と時系列の合体 です。 例として SSDSE-B-2026 で 北海道・東京都・大阪府 という個体 ($i$) を 2015 年・2018 年・2021 年 という時点 ($t$) で観測すれば、 個体 3 × 時点 3 = 9 観測のミニパネルになります。 横の比較(地域差)と縦の比較(時間変化)を 同時に 行えるため、 「東京の出生率が下がったのは年代の影響か、それとも東京固有の事情か」を分離できる点が最大の魅力です。

比喩としては 同じ生徒の身長を毎年測る のがパネルデータ、 毎年違うクラスの平均身長 はクロスセクション(pooled cross-section)、 同一クラスの平均だけを毎年 取るのが時系列です。 個体識別子 (Code/Prefecture) と時点識別子 (Year) を確実に保持することが、 後の固定効果・ランダム効果モデルの前提になります。

🎮 触って理解する

パネルデータは 個体(行)× 時点(列)の 2 次元 構造です。 スライダーで個体数 $N$・時点数 $T$ を変え、 グリッド上で ある個体の時系列(横方向 →)ある時点の横断面(縦方向 ↓) をハイライトしながら、 観測数 $N\times T$ と分散分解(個体間 between/個体内 within)がどう変わるかを体感してください。 グリッドのマスをタップ/クリックすると注目する個体 $i$・時点 $t$ を切り替えられます。 $T=1$ にすると横断面データ、 $N=1$ にすると時系列データ に退化する様子が最大のポイントです。

※ グリッドの数値は「高齢化率(%)風」のデモ用合成データ(決定論的に生成・毎回同じ)です。 実データの分散分解の実測値は下の 🧮 SSDSE-B 実値計算例(between 約 69.8%/within 約 30.1%)を参照。

散布図で見る — 個体内変動 vs 個体間変動

同じ変数でも「個体間(between)のばらつき」と「個体内(within)の年次変動」は別物です。 表示を切り替えて、 プールした生データ・個体平均だけ・個体平均を引いた偏差(within 変換)を見比べてください。 N=1 では between が消え、 T=1 では within が消えます。

分散分解(現在の N×T グリッド上で厳密計算)

全分散 = 個体間分散 + 個体内分散(各観測を母数 $N\times T$ で割った定義なので厳密に加法的)。 固定効果モデルは between を捨てて within だけ で係数を識別します。

🔎 深掘り解説

直感: パネルデータは「同じ対象を繰り返し観測した 2 次元データ」です。 横断面(ある年に全県を 1 回だけ)でも時系列(1 県を長期に)でもなく、 その両方を同時に持つため、 「地域差(縦の比較)」と「時間変化(横の比較)」を分離できます。 グリッドで行方向にたどれば 1 個体の歴史(時系列)、 列方向にたどればある時点のスナップショット(横断面)になります。

よくある落とし穴:系列相関—同一個体内の残差は時間的に相関するので、 通常の標準誤差は過小評価になり クラスタロバスト SE が必須。 ② 不均衡パネル(unbalanced)—個体ごとに観測年数が違うと、 上のグリッドのように綺麗な長方形にならない。 ③ 脱落(attrition)—退出する個体が体系的に異なると、 残った個体だけの分析にバイアスが乗る。 これらは横断面や単独時系列では現れない、 パネル特有の注意点です。

発展: 個体効果 $\mu_i$ を定数として消すのが 固定効果モデル(within 変換=上の「偏差」表示に対応)、 確率変数として扱うのが 変量効果モデル(between も使う)。 被説明変数のラグを右辺に入れる 動学パネル(Arellano-Bond GMM) では Nickell バイアスに注意します。 極限としては 横断面データ(T=1)時系列データ(N=1) がパネルの特殊ケースにあたります。

📐 定義・数式

🍰 まずはやさしく

数式で表したデータのルールです。

地域や時間の個別の影響を取り除くために使います。

県の特性と時代の流れを分けて考えます。

計算式を使って詳しく定義していきます。

パネル回帰の最も一般的な構造は二元誤差成分モデルです。

$$ y_{it} = \alpha + \boldsymbol{x}_{it}^{\top}\boldsymbol{\beta} + \mu_i + \lambda_t + \varepsilon_{it}, \quad i=1,\dots,N,\ t=1,\dots,T $$

ここで $y_{it}$ は個体 $i$ ・時点 $t$ の被説明変数、 $\mu_i$ は個体固有効果、 $\lambda_t$ は時点固有効果。 SSDSE-B-2026 ならば $i$ は 47 都道府県、 $t$ は調査年で、 $y$ を出生率、 $x$ を高齢化率・人口規模とすれば「地域要因 ($\mu_i$) と全国共通の景気要因 ($\lambda_t$) を吸収した純粋な政策効果 ($\beta$)」が推定できます。

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

記号意味SSDSE-B-2026 での具体例
$i$個体(クロスセクション単位)47 都道府県 (Prefecture)
$t$時点調査年 (Year)
$\mu_i$個体固定効果(時間で変わらない地域特性)気候・歴史・文化など測定困難な要因
$\lambda_t$時間効果(全国共通のショック)コロナ禍・消費税増税・景気循環
$\varepsilon_{it}$特異誤差(残差)説明変数で捉えきれないランダムなブレ

推定の際は、 個体固有効果 $\mu_i$ を 固定として扱うか(FE)ランダム変量として扱うか(RE) でモデルが分かれます。 Hausman 検定で選択するのが定番です。

🧮 SSDSE-B 実値計算例(47都道府県データ)

47 都道府県 × 複数年のパネル構造を持つ SSDSE-B を擬似パネル化し、 固定効果モデルを推定する完全再現例。

① 計算コード

▼ コード解説(ランダム効果(個体間+個体内))
🎯 解説: RandomEffects で個体差を確率変数として扱う。 個体特性が説明変数と無相関なら、 FE より効率的(標準誤差が小さい)。
📥 入力例: RandomEffects=True Hausman 検定で FE vs RE を選択
📤 実行例: FE の within R² ≈ 0.80 / RE の overall R² ≈ 0.66(実測) Hausman χ²(2)=0.38, p=0.83(本例は RE も可)
💬 読み方: ハウスマン検定で p<0.05 なら FE が安全。 個体特性が説明変数と相関する可能性が高い社会経済データでは FE が主流。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
import pandas as pd, numpy as np
import statsmodels.api as sm
from linearmodels.panel import PanelOLS, RandomEffects, compare

# SSDSE-B-2026 は 47都道府県 × 12年(2012-2023) の実パネル。
# 1行目=列コード, 2行目=日本語名 なので skiprows=[1] でコード行を列名にする
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df.rename(columns={'SSDSE-B-2026': 'Year'})          # 先頭列が年度
for c in ['A1101', 'A1303', 'A4101']:
    df[c] = pd.to_numeric(df[c], errors='coerce')
df['aging']      = df['A1303'] / df['A1101'] * 100        # 高齢化率(%) = 65歳以上/総人口
df['birth_rate'] = df['A4101'] / df['A1101'] * 1000       # 出生率(人口千対) = 出生数/総人口
df['log_pop']    = np.log(df['A1101'])                    # log 総人口
panel = df.set_index(['Prefecture', 'Year'])              # (個体, 時点) の2次元 index

y = panel['birth_rate']
X = sm.add_constant(panel[['aging', 'log_pop']])
# 固定効果モデル(県内変動のみ使用・県クラスタ標準誤差)
fe = PanelOLS(y, X, entity_effects=True).fit(cov_type='clustered', cluster_entity=True)
# 変量効果モデル(県間変動も使用、 仮定が満たされれば効率的)
re = RandomEffects(y, X).fit()
print(compare({'FE': fe, 'RE': re}))
▼ コード解説(プールド OLS(個体差無視))
🎯 解説: 個体差を無視して全 564 行(47県×12年)を 1 つの回帰式で推定。 個体特性が同質と仮定するが、 通常は仮定が崩れる。
📥 入力例: y = α + βX + ε n = 564(12 年 × 47 県)
📤 実行例: R² ≈ 0.67(プールOLS・実測) ただし誤差項に系列相関と異質性が残る
💬 読み方: プール OLS は比較ベースラインとして使い、 FE/RE と結果を比較するのが定石。 単独で結論に使うのは危険。

② 期待出力

項目 参考 解釈
FE高齢化率-0.354 (±0.029)県内で高齢化1pt↑→出生率(千対)約0.35↓
RE高齢化率-0.358 (±0.008)県間+県内。 FE とほぼ一致
FElog(総人口)+0.022県内の人口規模変化の効果は小さい
Hausmanχ²(2)0.38 (p=0.83)RE 棄却されず→本例は RE も可

👉 値は SSDSE-B-2026(2012-2023) の実測値。 同じ手順で他都道府県・他変数にも適用可能。

🧮 SSDSE-B-2026 拡張ハンズオン — 県内変動 vs 県間変動

パネル分析の最大の価値は「個体内の変動だけ」を取り出して回帰できる点にあります。 SSDSE-B-2026 を使い、 高齢化率(65歳以上人口÷総人口)の分散を県間(between)と県内(within)に分解します。

🎯 学習目的

「都道府県間のばらつき」と「都道府県内の年次変動」のどちらが大きいかを定量化し、 固定効果モデルが何を捨てるかを理解する。

📥 入力

SSDSE-B-2026 を「都道府県 × 年度」のパネルとして整形したもの。

📤 出力

between 分散 / within 分散の数値と比率。

💬 解説

SSDSE-B-2026 のような社会経済指標は通常、 「東京と沖縄の差」のような between 分散が支配的です。 固定効果モデルはこれを切り捨てて、 「同じ県の中での年次変動だけ」で係数を識別します。

🐍 分散分解スクリプト

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import pandas as pd
import numpy as np

# 実パネル: 1行目=コード, 2行目=日本語名 → skiprows=[1], cp932
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df.rename(columns={'SSDSE-B-2026': 'Year'})
df['A1101'] = pd.to_numeric(df['A1101'], errors='coerce')
df['A1303'] = pd.to_numeric(df['A1303'], errors='coerce')
df['aging'] = df['A1303'] / df['A1101'] * 100    # 高齢化率(%)

y = df['aging']
overall = y.mean()
between = df.groupby('Prefecture')['aging'].mean()                          # 県平均
within  = df['aging'] - df.groupby('Prefecture')['aging'].transform('mean')

var_total   = y.var()
var_between = (between - overall).pow(2).mean()
var_within  = within.var()
print(f'total   = {var_total:.2f}')
print(f'between = {var_between:.2f} ({100*var_between/var_total:.1f}%)')
print(f'within  = {var_within:.2f}  ({100*var_within/var_total:.1f}%)')

📤 実行結果

total = 12.10 between = 8.44 (69.8%) within = 3.65 (30.1%)

読み解きの観点

❓ よくある質問 — パネル分析の実務判断 10 問

Q1. パネルとは「縦と横」のどちら向きのデータ?

同じ個体(行)を時間(列方向に展開)で複数回観測したデータ。 ただし分析する際はlong-format(個体 ID、 時点、 値 の 3 列)に展開するのが標準。

Q2. 短い T で固定効果は安定するか

T が 2-3 程度では individual fixed effects は推定誤差が大きい。 N が大きければ実用上問題ない(Nickell バイアスは N に依らない)。

Q3. なぜ固定効果と DID が同じか

DID は「個体固定効果 + 時間固定効果 + 処置ダミー」の二元固定効果モデルと数学的に同値。 二期間ならば差分が one-way fixed effects と等価。

Q4. クラスタロバスト標準誤差は必須か

パネルでは個体内の系列相関が必ず存在するため、 通常の SE は過小評価される。 個体クラスタロバスト SE が標準。

Q5. パネルでの不均衡(unbalanced)対応

個体ごとに観測期間が異なるパネルは linearmodels.PanelOLS で自動対応。 ただし脱落理由が処置と相関する場合は IPW が必要。

Q6. 動学パネルの落とし穴

被説明変数のラグを右辺に入れると Nickell バイアス。 GMM(Arellano-Bond ・ Blundell-Bond)で対処。

Q7. 個体数 47 で十分か

パネルは「N × T = 観測数」なので、 T が 10 もあれば 47 × 10 = 470 で十分。 ただし個体ダミーの数に注意。

Q8. 何年分あれば「パネル」と呼べるか

2 期間以上で形式的にはパネル。 因果推論なら 3 期間以上で前期・処置期・後期の比較が可能。

Q9. パネルとリピートクロスセクションの違い

同じ個体を追跡するのがパネル、 各期に独立サンプリングがリピートクロスセクション。 SSDSE-B-2026 は都道府県を毎年観測するのでパネル。

Q10. 二元固定効果モデルが拾えない効果

「全国共通のショック × 県固有の応答」は二元固定効果では拾えない。 これは交互作用項や Mundlak 装置で補う。

🧮 数式に値を入れて手で計算する: パネルデータの観測数

合成データで N×T パネルのバランス度合いを計算する。

Step 1: 構成

項目
個体数 N50
期間 T10
バランス時 観測数500
実際の観測 (欠損あり)450

Step 2: バランス度

完全バランス = N×T = 500 バランス度 = 450/500 = 0.90 (90%) 欠損 = 50 obs (10%)

🐍 Python で再現

1
2
3
4
5
6
N, T = 50, 10
full = N * T
observed = 450
balance = observed / full
print(f"完全バランス: {full}")
print(f"バランス度: {balance:.2f}")

📤 実行結果

完全バランス: 500 バランス度: 0.90

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

🔍 解説深化 — プーリング・バイアスと標準誤差の実測

ここでは SSDSE-B-2026(47 都道府県 × 12 年=564 行のバランスドパネル、2012〜2023) の実測値だけを使い、 「なぜパネルなのか」を 直感 → 落とし穴 → 発展 の順にもう一歩深掘りします。 数値はすべて data/raw/SSDSE-B-2026.csv(cp932・skiprows=[1])から実際に計算した値で、 合成データは使いません。

🎨 直感 — 「個体 × 時間」で交絡を分離する

パネルは同じ個体(都道府県)を複数時点で追跡するため、 横断面(地域差)と時系列(時間変化)の良いとこ取りができます。 全 564 観測の分散を 個体間(between)個体内(within)に分解すると、 変数ごとに「どちらのばらつきが主役か」がはっきりします(下表・実測)。 固定効果モデルは between を捨てて within だけで係数を識別するため、 within 比率が小さい変数ほど固定効果推定の情報量が乏しくなります。

変数全分散between(個体間)within(個体内)
高齢化率 aging12.118.44(69.8%)3.65(30.1%)
出生率 birth_rate(千対)1.230.66(53.4%)0.57(46.5%)

👉 高齢化率は「東京と秋田の差」= between が約 7 割で支配的なのに対し、 出生率は within(同じ県の年次変動)も約半分を占める。 同じ 47 県パネルでも変数によって「パネルにする旨味」が違うと分かる。

⚠️ 落とし穴① — 個体異質性を無視した単純プーリングのバイアス

個体差 $\mu_i$ を無視して 564 行をひとつの回帰に放り込む プールド OLS は、 $\mu_i$ が説明変数と相関すると偏ります。 同じ「高齢化率 → 出生率(千対)」を 3 通りの推定量で出すと、 推定値そのものが動きます(実測)。

推定量使う変動aging 係数(実測)読み方
プールド OLSbetween+within を混合−0.317両者の分散加重平均。単独で使うと危険
between 推定県平均のみ(横断面)−0.283「高齢な県ほど出生率低い」地域差の関係
within(固定効果)県内の年次変動のみ−0.354同じ県内で高齢化1pt↑→出生率0.35↓

👉 プールド OLS(−0.317) は between(−0.283) と within(−0.354) の中間に位置する。 これは「プールド係数は between と within の分散加重平均」という定理そのものの実演。 因果的に意味があるのは通常 within(固定効果) の方で、 プールド OLS の値を鵜呑みにすると地域差(時間不変交絡)の混入を見逃す。

⚠️ 落とし穴② — 系列相関で標準誤差が過小評価される(実測 約 2.9 倍)

同一県内の残差は年をまたいで相関する(系列相関/クラスタ相関)ため、 それを無視した 素の標準誤差は過小評価になり、 検定が偽陽性に傾きます。 プールド OLS の aging 係数について、 素の SE と 県クラスタ・ロバスト SE を実測で比べると差は歴然です。

【aging 係数の標準誤差・実測】 プールド OLS : 素のSE = 0.0094 → 県クラスタSE = 0.0267 (約 2.9 倍に拡大) 固定効果(FE) : 素のSE = 0.0128 → 県クラスタSE = 0.0294 (約 2.3 倍に拡大)

👉 素の SE を信じると t 値が約 3 倍に水増しされ、 「強く有意」と誤読する。 パネルでは cov_type='clustered', cluster_entity=True(県クラスタ)が既定と考えるべき。 ただしクラスタ数 N=47 は漸近近似のぎりぎりの水準で、 ワイルドブートストラップや Driscoll-Kraay(横断相関にも頑健)での再確認が安全。

⚠️ 落とし穴③ — within 変換は「時間不変変数」を消す

固定効果(within 変換)は各県の平均を引くため、 県ごとに一定の変数(面積・海に面するか・県庁所在地など)は差し引きゼロになり係数が推定できません。 「固定効果は時間不変の交絡だけを除去する」裏返しで、 時間とともに動く未観測交絡(社会規範の変化など)は残ります。 時間不変変数の効果を見たいなら 変量効果モデルMundlak 装置(県平均を共変量に加える)を使います。 さらに被説明変数のラグを右辺に入れる動的パネルでは、 within 変換後に $y_{i,t-1}$ と誤差が相関して Nickell バイアス(T が短いほど深刻)が生じ、 Arellano-Bond GMM が必要になります。 不均衡パネル・脱落(attrition)の注意点は ⚠️ 落とし穴セクション を参照。

🚀 発展 — within / between / pooled から二元固定効果・動的パネルへ

🐍 実測の再現コード(3 推定量+クラスタ SE)

上の 🧮 実値計算例①dfaging / birth_rate / log_pop を作った続きに実行すると、 本節の実測値(pooled −0.317 / between −0.283 / within −0.354、 naiveSE 0.0094 / clusterSE 0.0267)を再現できます。

📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行) 都道府県 A1101(総人口) A1303(65歳以上人口) A4101(出生数) 北海道 5,092,000 1,681,000 24,430 東京都 14,086,000 3,205,000 86,348 沖縄県 1,468,000 350,000 12,549 …(全 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
32
import pandas as pd
import numpy as np

# この抜粋だけで動くように、都道府県 × 年度のパネルを作り直す
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df.rename(columns={'SSDSE-B-2026': 'Year'})
df['aging'] = df['A1303'] / df['A1101'] * 100          # 高齢化率 (%)
df['log_pop'] = np.log(df['A1101'])                    # 人口の対数
df['birth_rate'] = df['A4101'] / df['A1101'] * 1000    # 出生率 (人口千対)
df = df.dropna(subset=['aging', 'log_pop', 'birth_rate'])

import statsmodels.api as sm

X = sm.add_constant(df[['aging', 'log_pop']])
# (1) プールド OLS: 個体差を無視して 564 行を 1 本の回帰に
pooled = sm.OLS(df['birth_rate'], X).fit()
# (2) between 推定: 県平均だけ(横断面の関係)
m = df.groupby('Prefecture')[['aging', 'log_pop', 'birth_rate']].mean()
between = sm.OLS(m['birth_rate'], sm.add_constant(m[['aging', 'log_pop']])).fit()
# (3) within(固定効果)推定: 県平均を引いた偏差で回帰
d = df.copy()
for v in ['aging', 'log_pop', 'birth_rate']:
    d[v] = d[v] - d.groupby('Prefecture')[v].transform('mean')
within = sm.OLS(d['birth_rate'], d[['aging', 'log_pop']]).fit()

for name, r in [('pooled ', pooled), ('between', between), ('within ', within)]:
    print(name, round(r.params['aging'], 3))

naive = pooled.bse['aging']
cluster = sm.OLS(df['birth_rate'], X).fit(
    cov_type='cluster', cov_kwds={'groups': df['Prefecture']}).bse['aging']
print('naiveSE', round(naive, 4), 'clusterSE', round(cluster, 4))
pooled -0.317 between -0.283 within -0.354 naiveSE 0.0094 clusterSE 0.0267

👉 プールド係数が between と within の中間に来ること、 クラスタ SE が素の SE の約 2.9 倍になることが同時に確認できる。 これがパネルデータを「そのままプールしてはいけない」二大理由の実測的な裏付け。

🐍 Python 実装バリエーション(scikit-learn / scipy / Optuna)

A. scikit-learn による実装

▼ コード解説(ハウスマン検定(FE vs RE 選択))
🎯 解説: FE と RE の係数の差を χ² 統計量で検定。 p<0.05 なら FE 推奨。
📥 入力例: FE 推定値と RE 推定値 両者の共分散行列
📤 実行例: 手動 Within の高齢化率係数 ≈ -0.35(実測) → linearmodels の FE と一致
💬 読み方: ハウスマン検定は「RE の前提(個体効果と X が無相関)が成り立つか」を検査。 棄却されたら FE 一択。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import pandas as pd
import numpy as np

# この抜粋だけで動くように、都道府県 × 年度のパネルを作り直す
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df.rename(columns={'SSDSE-B-2026': 'Year'})
df['aging'] = df['A1303'] / df['A1101'] * 100          # 高齢化率 (%)
df['log_pop'] = np.log(df['A1101'])                    # 人口の対数
df['birth_rate'] = df['A4101'] / df['A1101'] * 1000    # 出生率 (人口千対)
df = df.dropna(subset=['aging', 'log_pop', 'birth_rate'])

from sklearn.linear_model import LinearRegression
# Within変換を手動実装(教育用): 各県の平均を引いてから回帰
panel_df = df.set_index(['Prefecture', 'Year'])
y = panel_df['birth_rate']
X = panel_df[['aging', 'log_pop']]
# 個体(県)内平均からの偏差
y_w = y - y.groupby(level='Prefecture').transform('mean')
X_w = X - X.groupby(level='Prefecture').transform('mean')
m = LinearRegression(fit_intercept=False).fit(X_w, y_w)
print('FE係数(手動Within):', dict(zip(X.columns, m.coef_.round(4))))
FE係数(手動Within): {'aging': -0.3536, 'log_pop': 0.0216}
▼ コード解説(年度ダミー(時間固定効果))
🎯 解説: TimeEffects=True で年度ダミーを追加。 全国共通のショック(コロナ・景気変動)を吸収。
📥 入力例: EntityEffects=True, TimeEffects=True 双方向固定効果モデル
📤 実行例: 双方向FEの within R² ≈ 0.42(実測) 年度ダミーで全国共通ショックを吸収
💬 読み方: 双方向 FE は社会経済データの標準モデル。 個体差と時間ショックの両方を吸収して、 真の因果関係に近づく。

B. scipy / statsmodels による実装

▼ コード解説(クラスター標準誤差)
🎯 解説: cov_type='clustered' で都道府県クラスター標準誤差を計算。 同一県内の誤差相関を補正。
📥 入力例: cluster_entity=True 47 クラスタ(県別)
📤 実行例: 係数推定値は同じ 標準誤差が 2-3 倍に t 値が下がる
💬 読み方: クラスター SE を使わないと、 系列相関がある場合に SE が過小評価されて t 値が水増しになる。 パネル分析の標準作法。
1
2
3
4
5
6
7
8
9
from scipy import stats
# Hausman 検定の核心:β_FE − β_RE を分散差で評価(簡易 z 版)
# 上の compare() で得た高齢化率の係数(実測値)を使う
beta_fe, se_fe = -0.3536, 0.0291
beta_re, se_re = -0.3576, 0.0079
z = (beta_fe - beta_re) / np.sqrt(se_fe**2 - se_re**2 + 1e-12)
p = 2 * (1 - stats.norm.cdf(abs(z)))
print(f'Hausman z = {z:.2f}, p = {p:.4f}')
print('p < 0.05 なら FE を採用、 そうでなければ RE で良い')
Hausman z = 0.14, p = 0.8864 p < 0.05 なら FE を採用、 そうでなければ RE で良い(本例は RE も可)
▼ コード解説(階差分析(first difference))
🎯 解説: diff() で前年差をとってから回帰。 個体固定効果を簡易に消去する手法。
📥 入力例: Δy_it = β Δx_it + Δε_it 各県の年差をとる
📤 実行例: n = 564 - 47 = 517 行 Δ 高齢化率 vs Δ 死亡率の関係
💬 読み方: 階差で時間不変効果を消去できるが、 サンプルが減るのと誤差相関が増えるトレードオフ。 FE の代替として使える。

C. Optuna でハイパラ・選択最適化

▼ コード解説(動学パネル(GMM))
🎯 解説: Arellano-Bond GMM で y_{t-1} を含む動学モデルを推定。 過去の応答が現在に影響する場合に必須。
📥 入力例: y_it = α + ρ y_{i,t-1} + β X_it + u_i + ε_it 内生性を解決する操作変数
📤 実行例: ρ̂ は前年からの慣性の強さ(0〜1) Hansen J 検定で操作変数の妥当性を確認
💬 読み方: 死亡率や経済指標は前年の値に依存(慣性)。 通常の FE では推定が偏るため、 GMM で内生性を解決する。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import optuna
from linearmodels.panel import PanelOLS

def objective(trial):
    # 時間効果の有無、 ラグ次数を選ぶ
    use_time = trial.suggest_categorical('time_effects', [True, False])
    lag = trial.suggest_int('lag', 0, 2)
    # 簡易実装:BIC で評価
    if lag > 0:
        pl = panel.assign(
            lag1=panel.groupby(level='Prefecture')['birth_rate'].shift(lag)).dropna()
        X_cols = ['aging', 'log_pop', 'lag1']
        m = PanelOLS(pl['birth_rate'], sm.add_constant(pl[X_cols]),
                     entity_effects=True, time_effects=use_time).fit()
    else:
        m = PanelOLS(panel['birth_rate'], sm.add_constant(panel[['aging', 'log_pop']]),
                     entity_effects=True, time_effects=use_time).fit()
    return -2 * m.loglik + np.log(m.nobs) * (len(m.params) + 1)

study = optuna.create_study(direction='minimize',
                            sampler=optuna.samplers.TPESampler(seed=0))
study.optimize(objective, n_trials=20)
print('Best:', study.best_params, 'BIC:', study.best_value)
▼ コード解説(年度別の散布図(年度効果の可視化))
🎯 解説: matplotlib で年度別に色分けした散布図を描画。 時間効果が視覚的に分かる。
📥 入力例: x: 高齢化率, y: 死亡率 color: 年度(2019-2023)
📤 実行例: panel_scatter.png 年度間で線が平行移動 → 時間ショックあり 傾きは一定 → 関係は安定
💬 読み方: 並行移動のパターンが見えれば双方向 FE が妥当。 傾きが年度で変わるなら交互作用項が必要。

D. ライブラリ早見表

ライブラリ / 関数 用途
linearmodels.panel.PanelOLS固定効果・変量効果・First Difference 推定
statsmodels.regression.mixed_linear_model.MixedLM混合効果モデル(ベイズ的)
pyfixest高速な固定効果回帰(R の fixest 互換)
differencesCallaway & Sant'Anna 等の DID 推定量

⚠️ 落とし穴(拡張版・各 100 文字以上)

① 固定効果でも残るバイアス(時変オミット変数)
固定効果は時間で動かないオミット変数を全て吸収するが、 時間とともに変動する未観測変数(例:政策意識・社会規範の変化)はバイアスを生む。 「FE だから内生性は解決」と過信せず、 操作変数や DID と組み合わせる、 もしくは因果推論の事前仮定を明示する必要がある。 計量経済学の入門書がよく省略する重要ポイント。
② Hausman 検定の結果だけでモデル選択しない
Hausman 検定で「変量効果が棄却されないから RE」とするのは早計。 検出力が低いケース(n×T が小さい、 共分散行列の推定不安定)では棄却できなくても FE が妥当な場合がある。 理論的に「個別効果と説明変数が独立か」を考えてから検定。 Mundlak アプローチによる代替検定も検討。
③ クラスタ標準誤差を忘れる
パネルデータは同一個体内で誤差が相関するため、 通常の OLS 標準誤差は過小評価。 検定で偽陽性が増え「有意」と誤判定。 必ずクラスタ・ロバスト標準誤差を使う(cov_type='clustered')。 クラスタ数が少ない(n=47 県)場合は、 ワイルドブートストラップ補正も検討。 Cameron & Miller (2015) のサーベイ参照。
④ 時間効果を忘れる(マクロショックの汚染)
リーマンショック・コロナのような共通ショックは年ダミーで吸収。 これを入れないと「変数 X が効いている」と見えても、 実は時間トレンドの偽相関。 time_effects=True も同時に指定するのが現代の標準。 双方向固定効果(two-way FE)と呼ばれる。 最近は Goodman-Bacon の DID 分解で問題点が指摘されている。
⑤ 動学パネル(ラグ依存変数)の内生性
$y_{i,t-1}$ を説明変数に入れると固定効果と誤差項が相関し、 OLS が不偏でない(Nickell bias)。 Arellano-Bond GMM や Blundell-Bond System GMM を使う。 短期パネル(T 小・N 大)で特に深刻。 SSDSE で「前年の出生率」を含めるモデルでは必ずこの問題に直面。
⑥ Unbalanced panel と attrition バイアス
個体ごとに観測期間が違う unbalanced panel では、 「退出する個体」と「残る個体」が体系的に異なるとバイアスが生じる。 例:倒産企業ほどデータが消えると、 残った企業の業績が過大評価される。 Heckman 選択モデルなどで補正する。
⑦ Within R² と Overall R² を混同
固定効果モデルの R² は3種類:Within(個体内変動の説明力)・Between(個体間)・Overall。 論文で報告する R² は文脈に合わせる必要があり、 Within R² の高さで「モデル良好」と早合点しない。 政策効果の議論なら Within を、 横断的説明なら Overall を見る。

⚠️ 条件・限界・誤解回避 — パネルデータ運用の現場知識

パネルデータは「個体 × 時点」の二次元構造を持つため、 通常のクロスセクションや単独の時系列とは前提も解析手順も異なる。 ここでは実務で頻発する 4 つの観点(適用条件・限界・誤解回避・チェックリスト)を整理し、 SSDSE-B-2026(47 都道府県 × 約 7 年)を例にいつ・どこで気を付けるかを具体化する。

📐 適用条件(パネル分析が成立するための前提)

  1. 個体識別子の一貫性: 各時点で同じ「個体(都道府県・企業・人)」を追跡できること。 都道府県は合併・分割が稀なので安全だが、 市町村レベルでは平成の大合併以降は ID 不連続が生じやすい。
  2. 時間軸の等間隔性(または明示): 年次・四半期・月次など、 観測間隔が揃っているか、 揃っていない場合は時点ダミーで吸収できる構造であること。 SSDSE-B-2026 は年次なので等間隔。
  3. 個体ごとの観測数 T ≥ 2: 固定効果や差分の差分を推定するには、 1 個体あたり最低 2 時点必要。 1 時点しかない個体は「クロスセクション」として別扱い。
  4. 欠損パターンの管理可能性: 「いつ・なぜ欠損したか」が把握できないと、 アンバランスドパネルでも推定にバイアスが乗る。 例: 平成市町村合併直後の人口データは構造的欠損。
  5. 固定効果が時間不変: 固定効果モデルでは「個体特有の効果が時間で変わらない」と仮定。 急激な制度変化(条例改正・特区指定)があった都道府県は別扱いが必要。

🚧 限界(パネル分析でも解けない問題)

  1. 時間変動する個体特性の交絡: 固定効果は「時間不変な個体特性」しか吸収できない。 都道府県の高齢化率のように時間とともに変化する交絡因子は別途モデル化が必要。
  2. 逆因果の解決はできない: パネル化しても X → Y か Y → X かは時系列的順序(lag 構造)と理論的議論で示すしかない。 グランジャー因果はあくまで「予測可能性」であり真の因果ではない。
  3. 標準誤差のクラスタ依存: 同一個体内の誤差は時系列相関を持つため、 通常の OLS 標準誤差は過小評価になる。 クラスタロバスト標準誤差(cluster-robust SE)の使用が必須。
  4. 短い T での収束性: T = 2, 3 のような短いパネルでは、 動的パネル(lag を含む)の推定量にバイアス(Nickell バイアス)が乗る。 SSDSE-B-2026(T = 7)でも要注意。
  5. 個体数 N の小ささ: 47 都道府県は N = 47 と少ない。 クラスタ標準誤差は N ≥ 30〜40 で漸近近似が機能するため、 47 はぎりぎりの水準。

💡 誤解回避(実務で陥りがちな勘違い)

  1. 「パネルなら自動で因果が分かる」は誤解: パネル化は識別の補助でしかない。 DID や fixed effects も「並行トレンド仮定」「時間不変仮定」が成立して初めて因果解釈できる。
  2. 「固定効果 = ランダム効果の上位互換」も誤解: ランダム効果は「個体効果と説明変数が無相関」のときに効率的。 Hausman 検定で適切に選択する。 SSDSE-B-2026 のような小サンプルではランダム効果の方が SE が小さくなる場合がある。
  3. 「時間ダミーは入れれば入れるだけ良い」も誤解: 時間ダミーは時間不変な共通ショックを吸収するが、 入れすぎると関心ある変数の効果(時間トレンドと連動するもの)も吸収してしまい、 解釈不能になる。
  4. 「アンバランスドパネルは捨てるべき」も誤解: 欠損が完全ランダム(MCAR)なら完全観測のみで分析しても不偏。 ただし MAR や MNAR の場合は逆にバイアスを生むので、 欠損パターンの分析が先決。
  5. 「ロングパネルとショートパネルは同じ」も誤解: T → ∞ のロングパネル(時系列重視)と N → ∞ のショートパネル(個体重視)では、 適用される漸近理論が違う。 SSDSE-B-2026 は両方とも中規模で、 ブートストラップでの確認が安全。

✅ 実務でのチェックリスト

💬 パネルデータ分析は「時系列+クロスセクション」の合わせ技。 表面上はリッチな情報を持つように見えても、 標準誤差・並行トレンド・欠損構造で躓くと結論が一変する。 上記チェックリストを毎回踏むことで、 「もっともらしいが間違った因果推論」を防ぐ。

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

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

🚀 実務応用の深掘り

典型的なプロジェクトの流れ

  1. 問題理解:ステークホルダーとの対話、 KGI/KPI 設定
  2. データ収集:内部DB、 公的データ(SSDSE等)、 API
  3. EDA:データの全体像把握、 異常検出
  4. 仮説立案:ドメイン知識からの仮説
  5. モデリング:シンプルから複雑へ段階的に
  6. 検証:CV、 ホールドアウト、 A/Bテスト
  7. 解釈:可視化、 SHAP、 部分依存プロット
  8. 展開:本番デプロイ、 監視

ベストプラクティス

論文・コンペでよく使う言い回し

日本語 英語
統計的に有意statistically significant
効果量effect size
95%信頼区間95% confidence interval (CI)
標本サイズsample size
検出力statistical power
第1種の誤りType I error / false positive
第2種の誤りType II error / false negative
多重比較問題multiple comparisons problem
過学習overfitting
汎化性能generalization
交差検証cross-validation (CV)

統計データ活用コンペでのコツ

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

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

📍 体系階層のパス

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

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

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

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

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

大きな円が小さな円を包含する Circle Packing 図。 「パネルデータ」は緑色でハイライト

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

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

長方形を入れ子に分割した Treemap 図。 各分野の規模感を面積で比較。 「パネルデータ」は緑色でハイライト

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

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

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

🔗 隣接手法への橋渡し

「パネルデータ」は単独で完結せず、 前後の手法と組み合わさって価値が発揮される。 入力データの準備 (上流)・同目的の代替手法との比較 (並列)・結果の活用 (下流) という 3 軸で隣接領域を整理する。

この上流・並列・下流の対応を地図化することで、 「パネルデータ」を中核に据えた分析パイプライン (データ準備 → 手法選択 → 結果の検証と展開) の全体像が見えてくる。

🌳 パネル分析の意思決定木 — 5 つの分岐

分岐 1: 個体を時間で繰り返し観測しているか

分岐 2: T と N の比率

分岐 3: 因果推論か記述か

分岐 4: パネルが balanced か unbalanced か

分岐 5: 時点が staggered な処置

📖 パネルデータの専門用語ミニ辞典 — 12 語

Panel Data
同じ個体を複数時点で観測したデータ。 縦断データとも。
Long Format
1 行 = 個体 × 時点の縦展開。 分析時の標準形式。
Wide Format
個体ごとに 1 行、 時点を列に並べた形式。 元データの形式に多い。
Within Variation
同じ個体内の時点間ばらつき。 固定効果モデルが使う情報。
Between Variation
個体間平均のばらつき。 クロスセクション情報。
Balanced Panel
全個体が全時点で観測されているパネル。
Unbalanced Panel
観測時点数が個体で異なるパネル。
Attrition
時点経過に伴う個体の脱落。 因果推論で深刻な問題。
Pooled Cross Section
異なる時点で独立にサンプリングされたデータ。 パネルではない。
CCE (Common Correlated Effects)
大 T 大 N での因子モデルパネル推定。
Dynamic Panel
被説明変数のラグを右辺に含むパネル。 GMM が必要。
Spatial Panel
個体間の空間的相互作用を考慮するパネル。

✅ パネル分析の最終チェックリスト 10 項目

  1. データを long-format に正しく展開したか。
  2. between 変動と within 変動の比率を確認したか。
  3. balanced か unbalanced かを明示したか。
  4. 固定効果と変量効果のどちらが適切かを Hausman 検定で判定したか。
  5. クラスタロバスト SE を使ったか。
  6. 時間固定効果の必要性を検討したか。
  7. 動学パネルなら GMM を検討したか。
  8. staggered な処置タイミングの場合、 新手法(Callaway-Sant'Anna 等)を使ったか。
  9. 脱落が処置と相関するなら IPW で補正したか。
  10. 結果を within R^2 / between R^2 / overall R^2 で分けて報告したか。

📝 まとめノート — パネルデータ

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

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

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

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

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

🖼 視覚資料: パネルデータの構造

パネルデータ(縦断データ)は「個体 × 時点」の 2 次元構造。 関連する 3 つの視覚で、 パネル独特の依存・時系列性・因果推定の枠組みを掴む。

パネルデータ構造
パネル(縦断)データの基本構造: 同じ個体を複数時点で観測する
時系列
時系列成分: パネル各個体は時間に沿って動く(時系列+クロスセクション)
差分の差分(DID)
DID(差分の差分): パネルデータで因果効果を推定する代表的設計

📝 理解度チェック — パネルデータ

以下の練習問題で理解度を確認しよう。 答えはあなた自身で考えて、 解説を読みながら整理する。

  1. 練習問題 1: SSDSE-B-2026 の都道府県 × 年次データで「出生率(出生数÷総人口)」を従属変数、 「高齢化率」を独立変数として固定効果モデルを推定するとき、 都道府県固定効果は何を吸収するか説明せよ。
  2. 練習問題 2: ランダム効果モデルと固定効果モデルのどちらを選ぶべきかを判定する Hausman 検定について、 帰無仮説と対立仮説を述べよ。
  3. 練習問題 3: DID(差分の差分)が因果推論に使えるための「並行トレンド仮定」を、 処置群と対照群の用語で説明せよ。
  4. 練習問題 4: T=2 のパネルで動的パネル(lag を含む)を推定するときに生じる Nickell バイアスとは何か、 N と T の関係で説明せよ。
  5. 練習問題 5: クラスタロバスト標準誤差が必要な理由を、 同一個体内の誤差の時系列相関の観点から述べよ。

💬 これらの問題に答えられれば、 パネルデータ分析の基礎は身に付いている。 自分で実データに当てはめて手を動かすことが、 概念定着への最短路。