論文一覧に戻る 📚 用語解説(ジャストインタイム型データサイエンス教育)
Granger因果検定
Granger Causality Test
「Xの過去値を加えるとYの予測が改善するか」を検定。統計的因果ではなく予測上の因果性。
時系列GrangerGranger因果グレンジャー

🔖 キーワード索引(補強)

Granger 因果性に関連する時系列概念のチップ集。

Granger 因果 VAR VECM 定常性 単位根検定 ADF 検定 KPSS 検定 共和分 差分処理 ラグ選択 AIC/BIC インパルス応答 分散分解 F 検定 Wald 検定 疑似因果 Sims 因果 Toda-Yamamoto 時間ラグ 情報フロー

🔖 キーワード索引 — 完全強化版

「グレンジャー因果」を理解するうえで必要なキーワードを 10 件以上提示します。 各チップから対応セクションへ移動できます。

30 秒結論 文脈 直感 数式 記号読み解き 実値計算 Python 実装 落とし穴 関連手法 関連用語 グループ教材 概念マップ

💡 30秒で分かる結論

🍰 まずはやさしく

予測のヒントを探す道具です。

あるデータが別のデータの予測に役立つか調べます。

スマホの利用時間で成績を予想できるか考えます。

この章では結論を短くまとめます。

📖 包括的解説 — この概念を完全マスター

📍 学習の3ステップ

  1. 定義を理解する:この概念は何か? 数式や条件を確認
  2. 具体例を見る:実データ(SSDSE 等)で計算してみる
  3. 応用する:自分のデータに適用、 結果を解釈

🔧 Python実装パターン

🎯 このコードでやること:Granger 因果検定の最小実装。合成した2系列(X が1期先行して Y を駆動)に対し、① ADF 検定で定常性を確認し、② statsmodelsgrangercausalitytests で「X の過去を加えると Y の予測が改善するか」をラグ別に F 検定/尤度比検定し、③ 逆向き(Y→X)も検定して因果の非対称性を確かめる。実データが非定常なら df.diff() で差分化してから渡す。

 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
import numpy as np, pandas as pd
from statsmodels.tsa.stattools import adfuller, grangercausalitytests

# --- 合成時系列:X の過去が Y を駆動する(X_{t-1} -> Y_t)---
rng = np.random.default_rng(42)
n = 200
x = np.zeros(n); y = np.zeros(n)
for t in range(1, n):
    x[t] = 0.5 * x[t-1] + rng.normal(0, 1)
    y[t] = 0.3 * y[t-1] + 0.6 * x[t-1] + rng.normal(0, 1)
df = pd.DataFrame({'X': x, 'Y': y})

# --- (1) 定常性チェック(ADF検定:p<0.05 で定常。非定常なら df.diff() で差分化)---
for c in ['X', 'Y']:
    stat, p = adfuller(df[c])[:2]
    print(f'ADF {c}: stat={stat:6.2f}, p={p:.4f} -> {"定常" if p < 0.05 else "非定常"}')

# --- (2) Granger因果検定:X の過去を加えると Y の予測が改善するか ---
def granger_pvalues(data, cause, effect, maxlag=3):
    # data[[effect, cause]] の順で渡すと「cause -> effect」を検定
    res = grangercausalitytests(data[[effect, cause]], maxlag=maxlag, verbose=False)
    print(f'\n[{cause} -> {effect}] ラグ別 p 値(F検定 / 尤度比検定)')
    for lag in range(1, maxlag + 1):
        f_p  = res[lag][0]['ssr_ftest'][1]      # F検定
        lr_p = res[lag][0]['lrtest'][1]          # 尤度比検定
        mark = '★有意' if f_p < 0.05 else '  '
        print(f'  lag={lag}: F検定 p={f_p:.4f}, 尤度比 p={lr_p:.4f}  {mark}')

granger_pvalues(df, cause='X', effect='Y')   # 本命:X -> Y
granger_pvalues(df, cause='Y', effect='X')   # 対照:Y -> X
📤 実行結果(上記コードの実測出力) ADF X: stat= -8.77, p=0.0000 -> 定常 ADF Y: stat= -8.79, p=0.0000 -> 定常 [X -> Y] ラグ別 p 値(F検定 / 尤度比検定) lag=1: F検定 p=0.0000, 尤度比 p=0.0000 ★有意 lag=2: F検定 p=0.0000, 尤度比 p=0.0000 ★有意 lag=3: F検定 p=0.0000, 尤度比 p=0.0000 ★有意 [Y -> X] ラグ別 p 値(F検定 / 尤度比検定) lag=1: F検定 p=0.4748, 尤度比 p=0.4708 lag=2: F検定 p=0.2678, 尤度比 p=0.2588 lag=3: F検定 p=0.0562, 尤度比 p=0.0501
💬 読み方:X→Y は全ラグで p<0.05(★)= X の過去は Y の予測を改善する= Granger 因果あり。逆向き Y→X は p>0.05 で非有意。このように向きで結果が非対称になるのが Granger 因果の要点。ただし「予測が改善する」だけで、介入で Y が変わる真の因果を保証しない点に注意(因果関係参照)。

📚 統計概念マップでの位置

このページの上にある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()

🚧 一般的な落とし穴と対策

📊 結果報告の標準フォーマット

🌐 関連分野での応用

🎓 さらに学ぶための文献

🔗 統計用語ネットワーク

この概念は、 他の多くの統計概念と密接に関連しています。 ジャストインタイム型学習では、 必要に応じて関連用語へジャンプしながら全体像を構築します。

主要な関連概念のグループ

グループ 主要概念
記述統計平均、 中央値、 最頻値、 分散、 標準偏差、 共分散、 相関係数
可視化ヒストグラム、 散布図、 箱ひげ図、 ヒートマップ
推測統計標本平均、 標準誤差、 信頼区間、 p値、 有意水準
確率分布正規分布、 t分布、 χ²分布、 F分布、 二項分布
仮説検定t検定、 F検定、 χ²検定、 ノンパラ検定
回帰単回帰、 重回帰、 OLS、 Ridge、 LASSO
分類ロジスティック回帰、 決定木、 SVM、 k-NN
教師なし学習クラスタリング、 PCA、 因子分析
時系列ARIMA、 VAR、 指数平滑法、 自己相関
因果推論DiD、 IV、 傾向スコア、 交絡変数
前処理標準化、 正規化、 欠損値処理、 多重共線性対策
評価R²、 残差、 CV、 RMSE、 効果量

学習順序の推奨

  1. 記述統計(平均、 分散、 標準偏差)
  2. 可視化(ヒストグラム、 散布図)
  3. 確率分布(正規分布)
  4. 推測統計(標準誤差、 信頼区間、 p値)
  5. 仮説検定(t検定、 χ²検定)
  6. 相関と回帰(単回帰、 重回帰)
  7. 多変量解析(PCA、 クラスタリング)
  8. 機械学習(決定木、 RF、 NN)
  9. 時系列・因果推論(応用)

📝 実践練習 — SSDSE-B-2026 で挑戦

初級課題

  1. 東北6県の家計食料費の基本統計量を計算
  2. 食料費のヒストグラムを描く
  3. 食料費と教育費の散布図を描く
  4. 都道府県を「東日本/西日本」に分け、 平均を比較

中級課題

  1. 家計支出 5項目で相関行列を作成、 ヒートマップ可視化
  2. 食料費 → 教育費の単回帰を実行、 残差分析
  3. 家計5項目で PCA を実施、 バイプロット表示
  4. k-means (k=3) で都道府県をクラスタリング、 解釈

上級課題

  1. 地域別の家計パターンに有意差があるか ANOVA で検定
  2. 重回帰で教育費を予測、 多重共線性を VIF で確認
  3. Ridge/LASSO で正則化、 CV で α を最適化
  4. 階層クラスタリングと Ward 法で都道府県を分類、 デンドログラム作成

💡 30 秒で分かる結論 — 完全強化版

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

🍰 まずはやさしく

データのつながりを見る方法です。

どのデータが先に動いたかを確認するために使います。

人口の変化が出生数にどう影響するかを調べます。

この用語がどこで使われるかを確認します。

論文中に 「Granger因果検定」として登場する用語。

Granger因果検定 とは:「Xの過去値を加えるとYの予測が改善するか」を検定。統計的因果ではなく予測上の因果性。

📍 文脈ボックス — あなたが今見ているもの(完全強化版)

このセクションは「グレンジャー因果」を扱う 用語ページ です。 統計データ分析コンペティション(2026)の再現教材における中核用語のひとつで、人口 A1101 と出生数 A4101 の時系列でグレンジャー因果検定 という観点で SSDSE-B-2026(47 都道府県 × 複数年 × 100 超列)に紐づけられます。

位置づけ:相関線形回帰仮説検定 といった基礎用語群と並列であり、応用としては 内生性IVDIDクラスタリング 等へ繋がります。

🎨 直感で掴む — 完全強化版

🍰 まずはやさしく

データ分析のための眼鏡のようなものです。

隠れた影響関係を見つけるために使います。

部活の練習量と試合の結果の関係を考えます。

直感的にイメージして理解しましょう。

グレンジャー因果 を一言でいえば「人口 A1101 と出生数 A4101 の時系列でグレンジャー因果検定」。 47 都道府県という小さな母集団でも、 SSDSE-B-2026 の A1101 列に注目すると、 大都市圏と地方の差・人口規模に伴う相対比較など、 様々なパターンが見えてきます。

比喩でいうと、 グレンジャー因果 はデータ分析の「眼鏡」のようなもの。 同じデータでも眼鏡を変えれば、 平均(中心)・分散(ばらつき)・相関(連動)・因果(影響)と、 異なる情報が浮かび上がります。 SSDSE-B-2026 を題材に、 この眼鏡をかけてみるのが本ページの狙いです。

🎮 触って理解する

2 つの時系列 X(青)Y(オレンジ) を表示します。 Y は「自分の過去」と「X の過去」から生成されています。 スライダーで X の過去が Y の将来に効く強さラグ数 p を変えると、 下の 2 本の棒が更新されます。左は Y を自分の過去だけで予測した誤差(RSS制限、 右は X の過去も加えて予測した誤差(RSS非制限。 後者が 有意に 小さければ「X は Y をグレンジャー予測する」と判定されます。 グラフ上を左右にドラッグ(スマホはタッチ)しても強さを変えられます。

⚠️ 予測改善であって真の因果ではありません。 ここで検定しているのは「X の過去情報が Y の予測誤差を減らすか」だけです。 共通の先行変数(交絡)や 共通トレンド があると、 実際には因果が無くてもグレンジャー予測が有意になります。 「グレンジャー因果あり」は「時間的な先行・予測寄与あり」と読み替えるのが安全です。

💡 直感 — 過去の情報は将来予測を改善するか

グレンジャー因果の核心は「情報」です。今の Y を予測するのに Y 自身の過去 だけで十分なら、 X は Y に対して情報を持ちません。ところが X の過去を足したとたんに予測誤差がガクッと下がるなら、 「X には Y の未来を先取りする情報が含まれている」= X は Y をグレンジャー予測する、と考えます。 上の実験で β を上げると RSS非制限 が RSS制限 より小さくなり、F 統計量が大きく、p 値が小さくなる様子を確認してください。

⚠️ よくある落とし穴 — 予測 ≠ 因果

🚀 発展 — VAR・インパルス応答・非定常の注意

📐 数式または定義 — 完全強化版

🍰 まずはやさしく

予測のルールを数式にしたものです。

過去のデータがどれだけ役立つかを計算します。

昨日の買い物で今日の予算を予想するような仕組みです。

具体的な数式と記号の意味を学びます。

グレンジャー因果 の代表的な定義式は次のとおりです。

$$ y_t = \alpha_0 + \sum_{i=1}^p \alpha_i y_{t-i} + \sum_{j=1}^p \beta_j x_{t-j} + \varepsilon_t; \quad H_0:\beta_1=\cdots=\beta_p=0 $$

ここで使われる記号や演算の意味は次節で言葉に翻訳します。

🔬 数式を言葉で読み解く — 完全強化版

数式の各記号を、日本語の意味に変換します。

🧮 SSDSE-B-2026 で実値計算 — Granger 因果性

SSDSE-B-2026 を年度パネルとして並べ替えれば、 都道府県の時系列を作ることができます。 ここでは年次データを擬似時系列として Granger 因果性を計算します。

例:2変量で Granger 因果性検定

📤 出力の読み方
# grangercausalitytests は maxlag までの各ラグについて
# ssr based F test / likelihood ratio test の p 値を返す。
# あるラグで p < 0.05 なら「X の過去は Y の予測を改善する(Granger 因果あり)」。
# 逆向き(Y→X)も検定し、因果の非対称性を確認する。

💬 読み方:算出された統計量を判定基準と比較し、有意性/効果量を評価する。

🎯 このコードでやること:Granger 因果性 — 過去値の予測寄与に基づく因果推論に関連するステップ #4。主要な指標(係数・統計量・スコア)を算出します。

📥 入力の形
# Granger 検定に渡すのは「定常な2系列」を並べた DataFrame。
# 列は説明変数候補 X(原因側)と被説明変数 Y(結果側)の2列で足りる。
# 実データが非定常なら df.diff().dropna() で差分化してから渡す。
#      X        Y
# 0  ...      ...
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import pandas as pd
from statsmodels.tsa.stattools import grangercausalitytests

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1)
# 東京都の時系列を抽出(年度列が存在する想定)
tokyo = df[df['都道府県'] == '東京都'].sort_values(df.columns[0])
# 年度列は使わず、人口 A1101(総人口)と出生数 A4101 の2系列を使う
ts = tokyo[['総人口', '出生数']].dropna()

# Granger 因果性:列1 が 列2 を予測できるか(最大 3 ラグ)
res = grangercausalitytests(ts, maxlag=3, verbose=False)
for lag, r in res.items():
    print(f'lag={lag}: F={r[0]["ssr_ftest"][0]:.3f}, p={r[0]["ssr_ftest"][1]:.4f}')

例:VAR モデルでの因果性

📤 出力の読み方
# grangercausalitytests は maxlag までの各ラグについて
# ssr based F test / likelihood ratio test の p 値を返す。
# あるラグで p < 0.05 なら「X の過去は Y の予測を改善する(Granger 因果あり)」。
# 逆向き(Y→X)も検定し、因果の非対称性を確認する。

💬 読み方:p 値や信頼区間と合わせて読み、効果の有無+大きさを両輪で判断する。

🎯 このコードでやること:Granger 因果性 — 過去値の予測寄与に基づく因果推論に関連するステップ #5。仮説検定・モデル評価を行います。

📥 入力の形
# Granger 検定に渡すのは「定常な2系列」を並べた DataFrame。
# 列は説明変数候補 X(原因側)と被説明変数 Y(結果側)の2列で足りる。
# 実データが非定常なら df.diff().dropna() で差分化してから渡す。
#      X        Y
# 0  ...      ...
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import pandas as pd
from statsmodels.tsa.api import VAR

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1)
tokyo = df[df['都道府県'] == '東京都'].sort_values(df.columns[0])
cols = ['総人口', '出生数']  # 人口 A1101 と出生数 A4101
ts = tokyo[cols].dropna().diff().dropna()  # 1階差で定常化

model = VAR(ts)
selection = model.select_order(maxlags=2)  # 年12点の短系列なので小さめに
print('推奨ラグ (AIC/BIC):', selection.aic, selection.bic)
fit = model.fit(maxlags=2)
print(fit.test_causality(cols[0], [cols[1]], kind='f'))
📤 実行例(実測) 推奨ラグ (AIC/BIC): 2 2 <statsmodels.tsa.vector_ar.hypothesis_test_results.CausalityTestResults object. H_0: 出生数 does not Granger-cause 総人口: fail to reject at 5% significance level. Test statistic: 1.479, critical value: 4.459>, p-value: 0.284>

🧮 実値で計算してみる — SSDSE-B-2026 で グレンジャー因果(完全強化版)

SSDSE-B-2026(公的統計の社会・教育系データセット、 47 都道府県 × 10 年分超 × 100 以上の列)を用いて、 「グレンジャー因果」を体感します。 ファイル名は SSDSE-B-2026.csv、 読み込みは下記の Python コードで行います。

1
2
3
4
5
6
7
8
import pandas as pd

# SSDSE-B-2026 を読み込む(cp932 / Shift_JIS)
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', skiprows=[1], encoding='cp932')
print(df.shape)          # (564, 112)
print(df['SSDSE-B-2026'].unique())  # 含まれる年度
latest = df[df['SSDSE-B-2026'] == df['SSDSE-B-2026'].max()].copy()
print(latest[['Prefecture', 'A1101', 'A4101']].head())

ここで使った中心列 A1101 は SSDSE-B-2026 における 人口 A1101 と出生数 A4101 の時系列でグレンジャー因果検定 に関連する指標です。 算出例:

🧮 数式に値を入れて手で計算する: AR と AR+X モデルの RSS 比較

合成データで X→Y の Granger 検定統計量を概算する。

Step 1: モデル別残差平方和

モデルRSSパラメータ数
制約付き (Y のみ)502
非制約 (Y + X 過去)404

n=100 サンプル

Step 2: F 統計量

F = ((RSS_r - RSS_u)/q) / (RSS_u/(n-k_u)) q=2 (追加した X パラメータ数) RSS 差 = 10 F = (10/2) / (40/96) = 5 / 0.4167 ≈ 12.0 F(2, 96, 0.05) ≈ 3.09 → 12.0 > 3.09 → X は Y を Granger 因果

🐍 Python で再現

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from scipy import stats
rss_r, rss_u = 50, 40
n = 100
k_u = 4
q = 2
F = ((rss_r - rss_u)/q) / (rss_u/(n - k_u))
crit = stats.f.ppf(0.95, q, n - k_u)
print(f"F = {F:.2f}")
print(f"臨界値: {crit:.3f}")
print(f"Granger 因果あり: {F > crit}")

📤 実行結果

F = 12.00 臨界値: 3.091 Granger 因果あり: True

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

🐍 Python 実装バリエーション(statsmodels / scipy / arch / pmdarima)

1. statsmodels.tsa — Granger / VAR 標準実装

📤 出力の読み方
# grangercausalitytests は maxlag までの各ラグについて
# ssr based F test / likelihood ratio test の p 値を返す。
# あるラグで p < 0.05 なら「X の過去は Y の予測を改善する(Granger 因果あり)」。
# 逆向き(Y→X)も検定し、因果の非対称性を確認する。

💬 読み方:表示された数値テーブルから個別の都道府県の位置づけを読み取る。

🎯 このコードでやること:Granger 因果性 — 過去値の予測寄与に基づく因果推論に関連するステップ #6。結果を整形して表示します。

📥 入力の形
# Granger 検定に渡すのは「定常な2系列」を並べた DataFrame。
# 列は説明変数候補 X(原因側)と被説明変数 Y(結果側)の2列で足りる。
# 実データが非定常なら df.diff().dropna() で差分化してから渡す。
#      X        Y
# 0  ...      ...
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import pandas as pd
from statsmodels.tsa.stattools import grangercausalitytests, adfuller
from statsmodels.tsa.api import VAR

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1)
tokyo = df[df['都道府県'] == '東京都'].sort_values(df.columns[0])
ts = tokyo[['総人口', '出生数']].dropna()

# まず定常性チェック
for c in ts.columns:
    stat, p = adfuller(ts[c])[:2]
    print(f'{c}: ADF stat={stat:.3f}, p={p:.4f}')

# Granger
res = grangercausalitytests(ts.diff().dropna(), maxlag=3, verbose=False)

2. scipy.stats — F検定で簡易 Granger

📤 出力の読み方
# grangercausalitytests は maxlag までの各ラグについて
# ssr based F test / likelihood ratio test の p 値を返す。
# あるラグで p < 0.05 なら「X の過去は Y の予測を改善する(Granger 因果あり)」。
# 逆向き(Y→X)も検定し、因果の非対称性を確認する。

💬 読み方:SSDSE-B-2026 の実値に当てはめると教科書例より分散が大きいことに注意。

🎯 このコードでやること:Granger 因果性 — 過去値の予測寄与に基づく因果推論に関連するステップ #7。47都道府県データに当てはめて確認します。

📥 入力の形
# Granger 検定に渡すのは「定常な2系列」を並べた DataFrame。
# 列は説明変数候補 X(原因側)と被説明変数 Y(結果側)の2列で足りる。
# 実データが非定常なら df.diff().dropna() で差分化してから渡す。
#      X        Y
# 0  ...      ...
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import numpy as np
import pandas as pd
from scipy import stats
import statsmodels.api as sm

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1)
tokyo = df[df['都道府県'] == '東京都'].sort_values(df.columns[0])
ts = tokyo[['総人口', '出生数']].dropna().values

# 制約モデルと非制約モデルの SSR を比較
def granger_f(y, x, lag=2):
    Y = y[lag:]
    X_rest = np.column_stack([y[lag-i-1:-i-1] for i in range(lag)])
    X_full = np.column_stack([Y]*0 + [y[lag-i-1:-i-1] for i in range(lag)] +
                             [x[lag-i-1:-i-1] for i in range(lag)])
    X_rest = sm.add_constant(X_rest); X_full = sm.add_constant(X_full)
    ssr_r = sm.OLS(Y, X_rest).fit().ssr
    ssr_f = sm.OLS(Y, X_full).fit().ssr
    n, k = len(Y), lag
    F = ((ssr_r - ssr_f) / k) / (ssr_f / (n - 2*k - 1))
    p = 1 - stats.f.cdf(F, k, n-2*k-1)
    return F, p

print(granger_f(ts[:, 0], ts[:, 1], lag=2))

3. arch — ブートストラップ Granger

📤 出力の読み方
# grangercausalitytests は maxlag までの各ラグについて
# ssr based F test / likelihood ratio test の p 値を返す。
# あるラグで p < 0.05 なら「X の過去は Y の予測を改善する(Granger 因果あり)」。
# 逆向き(Y→X)も検定し、因果の非対称性を確認する。

💬 読み方:別パターンと比べることで、手法選択の感度を体感できる。

🎯 このコードでやること:Granger 因果性 — 過去値の予測寄与に基づく因果推論に関連するステップ #8。比較・別パターンを検討します。

📥 入力の形
# Granger 検定に渡すのは「定常な2系列」を並べた DataFrame。
# 列は説明変数候補 X(原因側)と被説明変数 Y(結果側)の2列で足りる。
# 実データが非定常なら df.diff().dropna() で差分化してから渡す。
#      X        Y
# 0  ...      ...
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from arch.bootstrap import StationaryBootstrap
import numpy as np
import pandas as pd

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1)
tokyo = df[df['都道府県'] == '東京都'].sort_values(df.columns[0])
ts = tokyo[['総人口', '出生数']].dropna().values

def stat_func(data):
    # 簡易: 共分散を統計量に
    return np.cov(data[:, 0], data[:, 1])[0, 1]

bs = StationaryBootstrap(3, ts)
results = bs.apply(stat_func, 200)
print('ブートストラップ平均:', np.mean(results), '95%CI:', np.percentile(results, [2.5, 97.5]))

4. pmdarima — 自動 ARIMA で予測誤差比較

📤 出力の読み方
# grangercausalitytests は maxlag までの各ラグについて
# ssr based F test / likelihood ratio test の p 値を返す。
# あるラグで p < 0.05 なら「X の過去は Y の予測を改善する(Granger 因果あり)」。
# 逆向き(Y→X)も検定し、因果の非対称性を確認する。

💬 読み方:ハイパーパラメータで結果が大きく変わる場合は安定性を疑う。

🎯 このコードでやること:Granger 因果性 — 過去値の予測寄与に基づく因果推論に関連するステップ #9。ハイパーパラメータを変えて再計算します。

📥 入力の形
# Granger 検定に渡すのは「定常な2系列」を並べた DataFrame。
# 列は説明変数候補 X(原因側)と被説明変数 Y(結果側)の2列で足りる。
# 実データが非定常なら df.diff().dropna() で差分化してから渡す。
#      X        Y
# 0  ...      ...
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import pmdarima as pm
import pandas as pd

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1)
tokyo = df[df['都道府県'] == '東京都'].sort_values(df.columns[0])
ts = tokyo[['総人口', '出生数']].dropna()
y, x = ts.iloc[:, 0], ts.iloc[:, 1]

# 単独 ARIMA vs 外生変数つき ARIMA
mod1 = pm.auto_arima(y, seasonal=False)
mod2 = pm.auto_arima(y, exogenous=x.values.reshape(-1,1), seasonal=False)
print(f'BIC 単独: {mod1.bic():.2f}, 外生あり: {mod2.bic():.2f}')
print('外生変数で予測改善 →', mod2.bic() < mod1.bic())

5. 多変量 VAR と インパルス応答

📤 出力の読み方
# grangercausalitytests は maxlag までの各ラグについて
# ssr based F test / likelihood ratio test の p 値を返す。
# あるラグで p < 0.05 なら「X の過去は Y の予測を改善する(Granger 因果あり)」。
# 逆向き(Y→X)も検定し、因果の非対称性を確認する。

💬 読み方:最終結果は CSV/プロットとして保存しておくと後続分析で再利用できる。

🎯 このコードでやること:Granger 因果性 — 過去値の予測寄与に基づく因果推論に関連するステップ #10。最終結果のまとめ・保存を行います。

📥 入力の形
# Granger 検定に渡すのは「定常な2系列」を並べた DataFrame。
# 列は説明変数候補 X(原因側)と被説明変数 Y(結果側)の2列で足りる。
# 実データが非定常なら df.diff().dropna() で差分化してから渡す。
#      X        Y
# 0  ...      ...
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import pandas as pd
from statsmodels.tsa.api import VAR
import matplotlib.pyplot as plt

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1)
tokyo = df[df['都道府県'] == '東京都'].sort_values(df.columns[0])
ts = tokyo[['総人口', '出生数', '死亡数']].dropna().diff().dropna()

model = VAR(ts).fit(maxlags=2)
irf = model.irf(10)
irf.plot()
plt.savefig('var_irf.png', dpi=120, bbox_inches='tight')

🐍 Python 実装 — 完全強化版

scipy / pandas / scikit-learn / statsmodels を中心とした標準的な実装例です。 まず CSV を読み込み、 次に グレンジャー因果 の解析を行います。

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

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', skiprows=[1], encoding='cp932')
df = df[df['SSDSE-B-2026'] == df['SSDSE-B-2026'].max()].copy()

x = df['A1101'].astype(float).values
y = df['A4101'].astype(float).values

# 基本統計量
print('n            =', len(x))
print('mean(x)      =', np.mean(x))
print('std(x)       =', np.std(x, ddof=1))

# グレンジャー因果 の代表的計算(用途に応じて scipy/statsmodels を切替える)
r, p = stats.pearsonr(x, y)
print(f'Pearson r = {r:.4f}, p = {p:.4g}')
rs, ps = stats.spearmanr(x, y)
print(f'Spearman rho = {rs:.4f}, p = {ps:.4g}')

用途別の追加実装:

1
2
3
4
5
6
7
8
9
# 標準化と簡易クラスタリングの例
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import KMeans

X = df[['A1101', 'A4101']].astype(float).values
Xs = StandardScaler().fit_transform(X)
km = KMeans(n_clusters=4, n_init=10, random_state=0).fit(Xs)
df['cluster'] = km.labels_
print(df[['Prefecture', 'A1101', 'A4101', 'cluster']].head(10))
1
2
3
4
5
6
7
8
# 時系列(年度別・47都道府県平均の A1101)— 例として ARIMA 系の前処理
import statsmodels.api as sm

df_all = pd.read_csv('data/raw/SSDSE-B-2026.csv', skiprows=[1], encoding='cp932')  # 全年度パネルを再読込
ts = df_all.sort_values('SSDSE-B-2026').groupby('SSDSE-B-2026')['A1101'].mean()
print(ts.tail())
res = sm.tsa.stattools.adfuller(ts)
print('ADF stat:', res[0], 'p:', res[1])

⚠️ Granger 因果性の落とし穴(補強・各 100 文字以上)

① 「Granger 因果性 = 真の因果」と誤解する
Granger 因果は「過去の x が y の予測精度を高める」だけで、 物理的・操作的な因果ではない。 共通の先行変数(confounder)があれば偽の Granger 因果が出る。 例:天気予報がアイス売上を Granger 引き起こすように見えても、 真の原因は気温。 真の因果には介入実験や DAG が必要。
② 単位根(非定常性)を放置する
非定常な系列で VAR を回すと spurious regression(疑似回帰)になり、 F 値が有意になりやすい。 必ず ADF・KPSS で単位根を検査し、 差分処理(1次差分・季節差分)で定常化する。 さらに 2系列が共和分関係にあれば VECM を使う。 「差分してから検定」が基本ルール。
③ ラグ長の選択を恣意的に決める
最適ラグを目視で選ぶと結果が変わってしまう。 AIC, BIC, HQIC, FPE などの情報量規準で systematicに選ぶ。 BIC は簡素なモデルを好み、 AIC はやや複雑を許容。 報告時は「BIC 最小ラグを採用」と明示。 複数規準で異なる場合は、 結果の頑健性を確認する。
④ 短い時系列(T < 30)で実行する
Granger 因果検定は漸近分布に基づくので、 T が小さいとサイズ歪み(α が膨張)が大きい。 経験則として 1ラグあたり 30 観測以上、 4ラグなら最低 120 観測ほしい。 SSDSE のように T=20-30 のデータでは慎重な解釈が必要。 ブートストラップ補正も検討する。
⑤ 高頻度→低頻度の集計で因果関係が消える
日次データを月次に集計してから Granger を回すと、 月内のリードラグ構造が平均化されて検出できなくなる(temporal aggregation bias)。 可能なら元の高頻度データで分析するか、 mixed-frequency VAR (MIDAS) で対応する。 「分析の時間粒度」を意識的に選ぶ。
⑥ 季節性・構造変化の無視
強い季節性や政策変更による構造ブレイクを無視して Granger を回すと、 偽の因果が頻発する。 X-12-ARIMA で季節調整し、 Chow 検定や Bai-Perron 検定でブレイクを確認する。 ブレイクのある期間はサブサンプル分析するか、 ダミー変数で対応するのが定石。
⑦ 多変量で同時に多くの方向を検定し α 膨張
n 変数の VAR では n*(n-1) 通りの方向ペアを検定することになり、 多重比較で偽発見率が爆増する。 Bonferroni か FDR (Benjamini-Hochberg) で α を補正する。 また「全方向有意」になった場合は、 多重共線性やデータ準備の問題を疑う。

⚠️ 落とし穴 — 完全強化版

グレンジャー因果 を実務で扱う際に踏みやすい落とし穴を 5 件挙げます。

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

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つの視点で体系を理解する

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

📍 体系階層のパス

🌐 統計・データサイエンス › 因果推論 › 因果手法 › Granger因果検定

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

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

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

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

大きな円が小さな円を包含する Circle Packing 図。 「Granger因果検定」は緑色でハイライト

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

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

長方形を入れ子に分割した Treemap 図。 各分野の規模感を面積で比較。 「Granger因果検定」は緑色でハイライト

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

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

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

🗺 概念マップ — 完全強化版

🧭 解説深化 — 直感・落とし穴・発展(追記)

ここまでの本文・ウィジェットに加えて、グレンジャー因果を「予測因果」として腹落ちさせるための追補です。既存の説明と重複する部分もありますが、初学者が最短で誤解を避けられるよう、直感 → 落とし穴 → 発展の順に整理し直しています。

🎨 直感 — 「過去の情報が将来予測を助けるか」

グレンジャー因果の本質は「時間的先行」と「予測寄与」の2点に尽きます。
今の Y を当てるのに Y 自身の過去 だけで十分か、それとも X の過去 を足すと予測誤差が有意に減るか——これだけを見ています。X を足して初めて予測が改善するなら「X の過去には Y の未来を先取りする情報が含まれる」=「X は Y をグレンジャー予測する」と読みます。

⚠️ 落とし穴(重要)— グレンジャー因果 ≠ 真の因果

グレンジャー因果は誤用が非常に多い概念です。以下は「有意に出たのに結論を誤る」典型パターンです。

落とし穴 何が起きるか 対処
共通原因・交絡第3変数 Z が X と Y を先に動かすと、X→Y が偽陽性で有意になる交絡の検討/条件付きグレンジャー因果で Z を統制
非定常・共通トレンド両系列が上昇トレンドを共有するだけで見せかけの因果が出る(見せかけの回帰)定常性を ADF/KPSS で確認し差分化。共和分なら VECM
ラグ次数の選択ラグを変えると有意・非有意が入れ替わる(恣意的選択で p-hacking に)AIC/BIC で系統的に選び、採用基準を明示(ラグ変数
非線形関係の見落とし線形 VAR は非線形依存を検出できず「因果なし」と誤判定伝達エントロピー等の情報論的手法(情報エントロピー)を併用
瞬時因果・双方向同時点の影響(同期)や双方向フィードバックはラグ検定では捉えにくい両方向を検定し、瞬時相関は別途 IRF・構造 VAR で評価
短い時系列T が小さいと漸近分布が近似できず検出力が低い(サイズ歪み)最低でも 1ラグあたり30観測目安。少数点ではブートストラップ補正

⚠️ 合言葉:「グレンジャー因果あり」は「時間的先行・予測寄与あり」と読み替える。介入で結果が変わる真の因果(因果関係)とは常に区別して報告します。

🚀 発展 — VAR・条件付き・非線形・真の因果推論

🧮 実データで確認 — 東京都の総人口 A1101 × 出生数 A4101(SSDSE-B-2026 実測)

SSDSE-B-2026 の東京都を 2012–2023 年の12点の時系列として取り出し、実際にグレンジャー因果検定を回した結果です(encoding='cp932', skiprows=[1] で読み込み)。原系列は明確に非定常なので1階差で定常化してから検定しました。

📤 実測出力(東京都・2012–2023, n=12) # レベル(原系列)の定常性 → いずれも非定常 ADF A1101(総人口): stat= 0.605, p=0.988 -> 非定常 ADF A4101(出生数): stat= 2.220, p=0.999 -> 非定常 # 1階差(n=11)でグレンジャー因果検定(F検定 p 値) [A1101 -> A4101] lag=1: F=0.187, p=0.6785 [A1101 -> A4101] lag=2: F=0.002, p=0.9979 [A4101 -> A1101] lag=1: F=1.723, p=0.2307 [A4101 -> A1101] lag=2: F=1.479, p=0.3305

💬 読み方(重要な注意つき):どの向き・どのラグでも p>0.05 で、統計的にはグレンジャー因果は検出されませんでした。ただしこれは「因果が無い証明」ではありません。わずか12年(差分後11点)という極端な短系列では検定の検出力が非常に低く、真に効果があっても見逃しやすい(第2種の過誤)。都道府県×年度パネル(47県×12年)をパネル手法でプールする、より長期の系列を使う、といった対処が必要です。短系列での「有意でない」も「有意」も、そのまま因果の結論にしないことが最大の教訓です。

🔗 関連ページ(このサイト内・実在ページのみ)

※ 「伝達エントロピー」「VECM」「Toda-Yamamoto 検定」「インパルス応答」等は本サイトに独立ページが無いため、本文中では用語のみの言及にとどめています。

🔗 隣接手法への橋渡し

「グレンジャー因果」は単独で完結する手法ではなく、 隣接領域と連携することで真価を発揮する。

上流の VAR モデル・定常性検定 (ADF) で前提を確認し、 並列の Transfer Entropy・Convergent Cross Mapping と非線形版を比較し、 下流の構造 VAR・インパルス応答関数で因果効果を解釈する。 グレンジャー因果は「予測改善」という限定的因果概念で、 必ず真の介入因果 (Pearl 流) と区別して報告する。

🌳 手法選択フロー

「granger causality」を含む手法選択は、 データの性質・分析目的・運用制約の 3 軸で決まる。 以下に典型シナリオと対応する手法の組合せを示す。

典型シナリオ別の手法選択

シナリオ重視する観点候補手法
2系列の先行・遅行関係を知りたい定常性・ラグ選択・向きの非対称性ADF/KPSS → Granger 因果検定 → VAR / インパルス応答
系列が非定常だが長期均衡がありそう共和分の有無Johansen 検定 → VECM
非線形・情報論的な因果を見たい分布全体の依存転送エントロピー / Convergent Cross Mapping

選んだ後の検証ステップ

  1. 前処理確認: 標準化 / 欠損処理 / カテゴリ変数のエンコード が適切か
  2. ハイパラ調整: 交差検証で安定する値を選ぶ
  3. 性能評価: タスクに応じた指標 (RMSE / Accuracy / F1 / AUC / シルエット等) を複数併用
  4. 頑健性チェック: 別手法 / 別シードで結果が大きく違わないか確認
  5. 解釈: 結果を分野知識と照らし合わせ、 意味のある発見になっているか検討