見出し画像

⏰ 決定係数 R² と寄与率がつながる!

日常に統計・データ分析を取り入れてみませんか?

イントロ


統計検定2級と統計モデルを結ぶ 完全一致シリーズ の第4話は 決定係数と寄与率 です。
回帰分析と分散分析のつながりを楽しみましょう!


トピック


1. 今日の一言

重回帰分析の 決定係数 R² は、各説明変数の 寄与率の合計 と完全に一致する!

👉 説明変数が直交していれば、R² をきれいに分解できます。

⏰⏰⏰

2. 導入ストーリー

テストが返ってきたとき、友だちが話していました。

  • A君:勉強時間が長いほど点数は上がるよね。

  • B君:でも睡眠も大事だよ。寝不足だと成績が落ちるって言うし。

「テスト得点は、勉強時間と睡眠時間の両方でどのくらい説明できるんだろう?」

この「全体をどれくらい説明できるか」をまとめるのが 決定係数 R²
さらに「勉強」と「睡眠」それぞれがどのくらい貢献しているかを示すのが 寄与率 です。

3. データ例

30人の生徒について、勉強時間とテスト得点を記録しました。
※データはフィクションです。

$$
\begin{array}{ccc}
勉強時間(h) & 睡眠時間(h) & テスト得点 \\
\hline
\\
5.6 & 9.1 & 77 \\
2.9 & 6.6 & 63 \\
\vdots & \vdots & \vdots \\
\end{array}
$$

👉 実装では乱数で30人分のデータを生成します。

# インポート
import numpy as np

# データの作成
n = 30
rng = np.random.default_rng(seed=42)
study = rng.normal(5, 2, n).round(1)     # 勉強時間(平均5h)
sleep = rng.normal(7, 1, n).round(1)     # 睡眠時間(平均7h)
score = np.clip(
    (30 + 5*study + 3*sleep + rng.normal(0, 5, n)).round(0), 0, 100)  # テスト得点

# データの表示
print('【勉強時間】')
print(study)
print('【睡眠時間】')
print(sleep)
print('【得点】')
print(score)

【作成した仮想データの内容】

【勉強時間】
[5.6, 2.9, 6.5, 6.9, 1.1, 2.4, 5.3, 4.4, 5.0, 3.3, 6.8, 6.6, 5.1, 7.3, 5.9, 3.3, 5.7, 3.1, 6.8, 4.9, 4.6, 3.6, 7.4, 4.7, 4.1, 4.3, 6.1, 5.7, 5.8, 5.9]
【睡眠時間】
[9.1, 6.6, 6.5, 6.2, 7.6, 8.1, 6.9, 6.2, 6.2, 7.7, 7.7, 7.5, 6.3, 7.2, 7.1, 7.2, 7.9, 7.2, 7.7, 7.1, 7.3, 7.6, 5.5, 6.7, 6.5, 6.4, 6.7, 8.5, 6.1, 8.0]
【得点】
[77, 63, 83, 86, 62, 70, 75, 68, 78, 69, 81, 80, 70, 91, 82, 72, 80, 68,
90, 74, 77, 67, 82, 72, 64, 73, 78, 84, 80, 86]

時間と得点のデータをデータフレームにまとめます。

# インポート
import pandas as pd

# データフレーム化
df = pd.DataFrame({'勉強時間': study, '睡眠時間': sleep, '得点': score})

# 結果の表示
print('df.shape:', df.shape)
df.head()

【実行結果】

勉強時間と得点、睡眠時間と得点を回帰直線付きの散布図で可視化します。

# インポート
import matplotlib.pyplot as plt
import seaborn as sns
import japanize_matplotlib

# 描画領域の設定
fig, ax = plt.subplots(1, 2, figsize=(8, 4), sharey=True, tight_layout=True)
# 勉強時間と得点の散布図+回帰直線
sns.regplot(x='勉強時間', y='得点', data=df, ci=None,
            line_kws={'color':'tab:red'}, ax=ax[0])
# 睡眠時間と得点の散布図+回帰直線
sns.regplot(x='睡眠時間', y='得点', data=df, ci=None,
            line_kws={'color':'tab:green'}, ax=ax[1])
fig.suptitle('勉強時間・睡眠時間と得点の関係');

【実行結果】

「勉強時間が長いほど得点が高い」という正の相関が見られます。
一方で「睡眠時間と得点」の間に相関がないように見えます。
勉強時間は寄与が大きい、睡眠時間は寄与が小さい、こんな感じになるでしょう。

⏰⏰⏰

4. 確かめる

4.1 重回帰分析で R² を確認
重回帰分析を行って決定係数 R² を計算します。
statsmodels の ols を利用します。

# インポート
import statsmodels.formula.api as smf

# 回帰分析の実行
model = smf.ols('得点 ~ 勉強時間 + 睡眠時間', data=df).fit()
display(model.summary().tables[1])

# 決定係数の表示
print(f'決定係数 R² = {model.rsquared:.5f}')

【実行結果】

👉 R² が「モデル全体の説明力」を表します。

4.2 分散分析で寄与を計算
分散分析表を作成します。
重回帰の結果を statsmodels の anova_lm に渡して作成します。

# インポート
import statsmodels.api as sm

# 分散分析表の作成
anova_table = sm.stats.anova_lm(model, typ=1)  # タイプI平方和
display(anova_table.round(3))

【実行結果】
平方和 sum_sq に注目します。

各説明変数の寄与率を計算します。
👉 各説明変数の 平方和 / 全平方和 = 寄与率 になります。

# 寄与率の計算
contrib = anova_table[['sum_sq']].copy().set_axis(['平方和'], axis='columns')
contrib['寄与率'] = contrib / contrib.sum(axis=0)
contrib.round(3)

【実行結果】

👉 勉強時間の寄与率は 0.77 と高い値、睡眠時間の寄与率は 0.05 と僅か

4.3 R² と寄与率の一致を確認

# 勉強時間と睡眠時間の寄与率の合計
sum_contrib = contrib.loc[['勉強時間', '睡眠時間'], '寄与率'].sum()

# 結果の表示
print('寄与率の合計\t=', sum_contrib)
print('決定係数 R²\t=',  model.rsquared)

【実行結果】

👉 寄与率の合計 = R² と完全一致!

4.4 決定係数と寄与率のつながり

(注)この記事は「寄与率は平方和(sum_sq)の割合」としています。

R² の定義:

$$
R^2 = \frac{\text{SSR}}{\text{SST}}
$$

説明変数が直交しているとき、回帰の平方和(SSR)はきれいに分解できます:

$$
\text{SSR} = \text{SS}{\text{勉強}} + \text{SS}{\text{睡眠}}
$$

よって

$$
R^2 = \frac{\text{SS}_{\text{勉強}}}{\text{SST}} + \frac{\text{SS}_{\text{睡眠}}}{\text{SST}}
$$

一方で、説明変数が相関している(非直交)場合には「交互寄与(説明のかぶり)」が生まれます:

$$
\text{SSR} = \text{SS}{\text{勉強}} + \text{SS}{\text{睡眠}} + \text{交互寄与}
$$

ただし statsmodels の ANOVA(typ=1)などでは、この交互寄与がどちらかの変数に割り振られる仕組み

$$
\text{SS}_{\text{勉強 sm}} + \text{SS}_{\text{睡眠 sm}} = \text{SSR}
$$

になっており、最終的に

$$
R^2 = \cfrac{\text{SS}{\text{勉強 sm}} + \text{SS}{\text{睡眠 sm}}}{\text{SST}}
$$

が成立します。

👉 直交していれば「きれいな分解」として解釈できます。
👉 非直交でも statsmodels の結果で「寄与率の合計は必ず R² と一致する」ことが確認できます。

⏰⏰⏰

5. MLブリッジ

ML は機械学習の略称です。
scikit-learn の線形回帰でも確認できます。

# インポート
from sklearn.linear_model import LinearRegression

# 説明変数と目的変数の準備
X = df[['勉強時間','睡眠時間']]
y = df['得点']

# モデルの学習
reg = LinearRegression().fit(X, y)

# 決定係数の表示
print('決定係数 R²=', reg.score(X, y))

【実行結果】

👉 scikit-learn でも R² を出力できます。
👉 各説明変数の寄与率は直接は出ないが、R²を通じて「モデル全体の説明力」を統計と同じように確認できます。

⏰⏰⏰

6. ⚠️誤解注意

  • 完全一致は説明変数が直交している場合のみ
    実データでは説明変数どうしが相関し、寄与の分け方が一意でなくなる。

  • その場合、タイプ I 平方和・タイプ II 平方和・部分寄与率など複数の定義が存在する。

⏰⏰⏰

7. 架け橋のまとめ

  • R² = モデル全体の説明力

  • 寄与率 = 各変数の寄与分(平方和 ÷ 全平方和)

  • 寄与率の合計 = R²(直交ならきれいに分解、非直交でも合計は一致)

👉 決定係数と寄与率は、統計モデリングにおける「全体と部分の関係」をシンプルに示します。

⏰⏰⏰

8. 今日の小テスト

Q1. 決定係数 R² は何を表す?
→ 答え: モデル全体の説明力。

Q2. 寄与率はどう計算する?
→ 答え: 各説明変数の平方和 ÷ 全平方和。

Q3. R² と寄与率の和が完全一致するのはどんな場合?
→ 答え: 説明変数が直交しているときはきれいに分解できる。ただし非直交でも寄与率の合計は必ずR²に一致する。

⏰⏰⏰

9. 次回へつなぐ

今回の記事では、決定係数 R² と寄与率の完全一致を見ました。

では、カテゴリデータや確率モデルの適合度はどうやって検証するのでしょうか?
例えば「サイコロが公平かどうか」や「データが理論分布に従うか」といった問題です。

このときに使うのが 適合度の χ² 検定
実はこれも GLMの尤度比検定と完全に一致するのです。

👉 次回は「適合度 χ² 検定と尤度比検定の完全一致」を見ていきましょう!

⏰⏰⏰

おわり


シリーズ記事

次の記事

前の記事

目次

ブログの紹介


note で8つのシリーズ記事を書いています。
ぜひ覗いていってくださいね!

1.のんびり統計

統計検定2級の問題集を手がかりにして、確率・統計をざっくり掘り下げるブログです。
雑談感覚で大丈夫です。ぜひ覗いていってくださいね。
統計検定2級公式問題集CBT対応版に対応しています。
Python、EXCELのサンプルコードの配布もあります。

2.統計・データ分析とつながる

シリーズ「統計・データ分析とつながる」は、統計・データ分析との「つながり」を発掘して、コラム風に仕立てたブログシリーズです。
生成 AI の力を借りながら、統計・データ分析の入り口をイメージして、自由気ままに書きました。
たとえば…
・日常生活と統計のつながり
・統計検定2級からその先へのつながり
気楽にお読みいただけたら嬉しいです🍀

3.実験!たのしいベイズモデリング1&2をPyMC Ver.5で

書籍「たのしいベイズモデリング」・「たのしいベイズモデリング2」の心理学研究に用いられたベイズモデルを PyMC Ver.5で描いて分析します。
この書籍をはじめ、多くのベイズモデルは R言語+Stanで書かれています。
PyMCの可能性を探り出し、手軽にベイズモデリングを実践できるように努めます。
身近なテーマ、イメージしやすいテーマですので、ぜひぜひPyMCで動かして、一緒に楽しみましょう!

4.実験!岩波データサイエンス1のベイズモデリングをPyMC Ver.5で

書籍「実験!岩波データサイエンスvol.1」の4人のベイジアンによるベイズモデルを PyMC Ver.5で描いて分析します。
この書籍はベイズプログラミングのイロハをざっくりと学ぶことができる良書です。
楽しくPyMCモデルを動かして、ベイズと仲良しになれた気がします。
みなさんもぜひぜひPyMCで動かして、一緒に遊んで学びましょう!

5.楽しい写経 ベイズ・Python等

ベイズ、Python、その他の「書籍の写経活動」の成果をブログにします。
主にPythonへの翻訳に取り組んでいます。
写経に取り組むお仲間さんのサンプルコードになれば幸いです🍀

6.RとStanではじめる心理学のための時系列分析入門 を PythonとPyMC Ver.5 で

書籍「RとStanではじめる心理学のための時系列分析入門」の時系列分析をPythonとPyMC Ver.5 で実践します。
この書籍には時系列分析のテーマが盛りだくさん!
時系列分析の懐の深さを実感いたしました。
大好きなPythonで楽しく時系列分析を学びます。

7.データサイエンスっぽいことを綴る

統計、データ分析、AI、機械学習、Pythonのコラムを不定期に綴っています。
統計・データサイエンス書籍にまつわる記事が多いです。
「統計」「Python」「数学とPython」「R」のシリーズが生まれています。

8.Python機械学習プログラミング実践記

書籍「Python機械学習プログラミング PyTorch & scikit-learn編」を学んだときのさまざまな思いを記事にしました。
この書籍は、scikit-learnとPyTorchの教科書です。
よかったらぜひ、お試しくださいませ。

最後までお読みいただきまして、ありがとうございました。

いいなと思ったら応援しよう!

ネイピア DS 応援ありがとうございます。これからもがんばって記事を作成します!

この記事が参加している募集