MENU

R で行列計算を使って重回帰分析を行う方法

重回帰分析は行列計算をしているわけだが、実際どのような計算をしているのか、R を使って計算してみる。

>>もう統計で悩むのは終わりにしませんか? 

↑期間・数量限定で無料プレゼント中!

目次

サンプルデータの準備

使用するデータは ISLR パッケージの Carseats データ。

これはチャイルドシートの売り上げデータ。

パッケージのインストール方法は以下の通り。

install.packages('ISLR')

パッケージインストールの過去記事はこちら。

データセット内の連続データのみを扱う。

library(ISLR)
str(Carseats)
Carseats2 <- Carseats[,c(1:6,8,9)]
str(Carseats)

使用するデータは以下の通り。

Salesをほかの7つの変数で予測する重回帰モデルを作る。

> str(Carseats2)
'data.frame':   400 obs. of  8 variables:
$ Sales      : num  9.5 11.22 10.06 7.4 4.15 ...
$ CompPrice  : num  138 111 113 117 141 124 115 136 132 132 ...
$ Income     : num  73 48 35 100 64 113 105 81 110 113 ...
$ Advertising: num  11 16 10 4 3 13 0 15 0 0 ...
$ Population : num  276 260 269 466 340 501 45 425 108 131 ...
$ Price      : num  120 83 80 97 128 72 108 120 124 124 ...
$ Age        : num  42 65 59 55 38 78 71 67 76 76 ...
$ Education  : num  17 10 12 14 13 16 15 10 10 17 ...

lm() で計算してみる

行列を使って Step by Step で計算してみる前に、lm() を使って計算してみる。

lm2 <- lm(Sales~.,data=Carseats2)
summary(lm2)

結果はこちら。

> summary(lm2)
Call:
lm(formula = Sales ~ ., data = Carseats2)
Residuals:
Min      1Q  Median      3Q     Max
-5.0598 -1.3515 -0.1739  1.1331  4.8304
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept)  7.7076934  1.1176260   6.896 2.15e-11 ***
CompPrice    0.0939149  0.0078395  11.980  < 2e-16 ***
Income       0.0128717  0.0034757   3.703 0.000243 ***
Advertising  0.1308637  0.0151219   8.654  < 2e-16 ***
Population  -0.0001239  0.0006877  -0.180 0.857092
Price       -0.0925226  0.0050521 -18.314  < 2e-16 ***
Age         -0.0449743  0.0060083  -7.485 4.75e-13 ***
Education   -0.0399844  0.0371257  -1.077 0.282142
---
Signif. codes:  0***0.001**0.01*0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 1.929 on 392 degrees of freedom
Multiple R-squared:  0.5417,    Adjusted R-squared:  0.5335
F-statistic: 66.18 on 7 and 392 DF,  p-value: < 2.2e-16

>>もう統計で悩むのは終わりにしませんか? 

↑1万人以上の医療従事者が購読中

行列計算で実行する方法

データを行列にする

nとpはサンプルサイズとパラメータの数。

データを行列にする必要がある。

Xの最初の列に切片としてすべてのデータ行に1を入力した。

ちなみに[,1]は一列目のみを取り出す指示、[,-1]は一列目以外を取り出す指示。

as.matrix() は行列として扱う指示。

y <- as.matrix(Carseats2[,1])
n <- length(y)
p <- length(Carseats2[,-1])
X <- as.matrix(cbind("Intercept"=rep(1,n),Carseats2[,-1]))
str(y)
str(X)

yとXはstr()では以下のように見える。

> str(y)
num [1:400, 1] 9.5 11.22 10.06 7.4 4.15 ...
> str(X)
num [1:400, 1:8] 1 1 1 1 1 1 1 1 1 1 ...
- attr(*, "dimnames")=List of 2
..$ : chr [1:400] "1" "2" "3" "4" ...
..$ : chr [1:8] "Intercept" "CompPrice" "Income" "Advertising" ...

回帰係数ベクトルを求める(最小二乗法を行列で)

回帰係数の推定値ベクトル $ \boldsymbol{\hat{\beta}} $ を求めるための式は以下の通り。

$$ \boldsymbol{\hat{\beta}} = (\boldsymbol{X}^t \boldsymbol{X})^{-1} \boldsymbol{X}^t \boldsymbol{y} $$

R で計算してみる。

まず、$ \boldsymbol{X}^t \boldsymbol{X} $

これは転置 t() と、行列の掛け算%*%を使って以下のように書く。

t(X) %*% X

すると、行列にパラメータが配置された8×8の行列が計算される。

> t(X) %*% X
            Intercept CompPrice  Income Advertising Population    Price     Age Education
Intercept         400     49990   27463        2654     105936    46318   21329      5560
CompPrice       49990   6341324 3418378      330699   13153953  5873316 2655656    695265
Income          27463   3418378 2198045      186598    7260338  3165088 1463551    380072
Advertising      2654    330699  186598       35256     806772   310118  141322     36657
Population     105936  13153953 7260338      806772   36722296 12249952 5608130   1456118
Price           46318   5873316 3165088      310118   12249952  5587066 2454154    644111
Age             21329   2655656 1463551      141322    5608130  2454154 1242033    296583
Education        5560    695265  380072       36657    1456118   644111  296583     80024

次に、逆行列 $ (\boldsymbol{X}^t \boldsymbol{X})^{-1} $ はどうやって書くか。

これはsolve() を使って文字通り「解く」。

結果は8×8の行列になっている。

solve(t(X)%*%X)

この逆行列に右から $ \boldsymbol{X} $ の転置行列をかけて、さらに $\boldsymbol{y} $ を掛けると回帰係数ベクトルが計算される。

solve(t(X)%*%X) %*% t(X) %*% y

結果はこちら。

これがいわゆる最小二乗法で、行列を使うとこんな計算になる。

> solve(t(X)%*%X) %*% t(X) %*% y
[,1]
Intercept    7.7076934384
CompPrice    0.0939149066
Income       0.0128717129
Advertising  0.1308636707
Population  -0.0001239252
Price       -0.0925226099
Age         -0.0449743402
Education   -0.0399844437

これは、lm() を使った時のcoefficientsに一致する。

Estimateの列の数値が一致しているのがわかる。

> summary(lm2)$coefficients
               Estimate   Std. Error     t value     Pr(>|t|)
(Intercept)  7.7076934384 1.1176259965   6.8964873 2.145154e-11
CompPrice    0.0939149066 0.0078395225  11.9796718 2.153866e-28
Income       0.0128717129 0.0034756701   3.7033759 2.432641e-04
Advertising  0.1308636707 0.0151219066   8.6539134 1.302560e-16
Population  -0.0001239252 0.0006877272  -0.1801952 8.570924e-01
Price       -0.0925226099 0.0050520870 -18.3137403 1.409811e-54
Age         -0.0449743402 0.0060082977  -7.4853715 4.751078e-13
Education   -0.0399844437 0.0371257460  -1.0770004 2.821424e-01

回帰係数ベクトルに beta という名前を付けておく。

beta <- solve(t(X)%*%X) %*% t(X) %*% y

予測値y.hatを求めて、実測値yと散布図を描いてみる

実測値ベクトル $ \boldsymbol{X} $ と回帰係数ベクトル $ \boldsymbol{\hat{\beta}} $ を使って予測値 $ \hat{y} $ を計算する。

行列表現をすれば以下のようになる。

$$ \boldsymbol{\hat{y}} = \boldsymbol{X \beta} $$

R では、以下の通りのスクリプトになる。

予測値をy.hatとした。

y.hat <- X %*% beta

実測値 y と予測値 y.hat の散布図を描いてみた。

切片 0、傾き 1 の直線 y = x も描き入れた。

実測値と予測値が一致すれば直線状に並ぶはずだ。

実際には完全には予測できないので、直線状には並ばない。

plot(y.hat,y, xlim=c(0,15),ylim=c(0,15))
abline(a=0,b=1)

分散共分散行列を求める

次に、回帰係数の検定の準備として、分散共分散行列(V.beta)を求める。

V.betaの計算のために、誤差分散 sigmaE2 を先に計算しておく。

sigmaE2 <- sum((y-y.hat)^2)/(n-p-1)
V.beta <- sigmaE2*solve(t(X)%*%X)

回帰係数の検定

回帰係数の検定は、回帰係数の推定値と回帰係数の標準誤差の比を検定統計量として実施する。

回帰係数の標準誤差は、先ほど計算した分散共分散行列の対角成分 diag() の平方根 sqrt() だ。

SE.beta <- sqrt(diag(V.beta))
t <- beta/SE.beta
pt(abs(t), n-p-1, lower.tail=FALSE)*2

標準誤差(SE.beta)は以下の通り。

> matrix(SE.beta)
[,1]
[1,] 1.1176259965
[2,] 0.0078395225
[3,] 0.0034756701
[4,] 0.0151219066
[5,] 0.0006877272
[6,] 0.0050520870
[7,] 0.0060082977
[8,] 0.0371257460

t値は、回帰係数と標準誤差の比で計算される。

> t
[,1]
Intercept     6.8964873
CompPrice    11.9796718
Income        3.7033759
Advertising   8.6539134
Population   -0.1801952
Price       -18.3137403
Age          -7.4853715
Education    -1.0770004

最後に有意確率は以下の通り。

> pt(abs(t), n-p-1, lower.tail=FALSE)*2
[,1]
Intercept   2.145154e-11
CompPrice   2.153866e-28
Income      2.432641e-04
Advertising 1.302560e-16
Population  8.570924e-01
Price       1.409811e-54
Age         4.751078e-13
Education   2.821424e-01

これらはすべてlm() を使った結果と一致する。

> summary(lm2)$coefficients
               Estimate   Std. Error     t value     Pr(>|t|)
(Intercept)  7.7076934384 1.1176259965   6.8964873 2.145154e-11
CompPrice    0.0939149066 0.0078395225  11.9796718 2.153866e-28
Income       0.0128717129 0.0034756701   3.7033759 2.432641e-04
Advertising  0.1308636707 0.0151219066   8.6539134 1.302560e-16
Population  -0.0001239252 0.0006877272  -0.1801952 8.570924e-01
Price       -0.0925226099 0.0050520870 -18.3137403 1.409811e-54
Age         -0.0449743402 0.0060082977  -7.4853715 4.751078e-13
Education   -0.0399844437 0.0371257460  -1.0770004 2.821424e-01

重相関係数と寄与率

最後に、重相関係数と寄与率(重相関係数の二乗)の計算を示す。

重回帰式の当てはまりの良さを表す指標の一つが寄与率だ。

重相関係数は寄与率の平方根で、実測値 y と予測値 y.hat の相関係数である。

重相関係数は0.735976である。

> cor.test(y,y.hat)
Pearson's product-moment correlation
data:  y and y.hat
t = 21.688, df = 398, p-value < 2.2e-16
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 0.6875397 0.7778921
sample estimates:
     cor 
0.735976 

寄与率は、0.5416606である。

> R2 <- cor(y,y.hat)^2
> R2
[,1]
[1,] 0.5416606

寄与率がゼロでないのを確認する検定は以下の通り。

F <- (R2/p)/((1-R2)/(n-p-1))
pF <- pf(F, p, n-p-1, lower.tail=FALSE)

結果は以下の通り。

> F
[,1]
[1,] 66.18021
> pF
[,1]
[1,] 1.413772e-62

寄与率及び寄与率の検定結果は、lm() の summary()で表示される最下段の記述に現れる。

Multiple R-squared:  0.5417,    Adjusted R-squared:  0.5335
F-statistic: 66.18 on 7 and 392 DF,  p-value: < 2.2e-16

まとめ

重回帰分析を step by step で R を用いて、行列計算で実行してみた。

参考になれば。

参考書籍

教科書は、「医学への統計学」

15.3 重回帰分析

医学への統計学 (統計ライブラリー)

新版はこちら

医学への統計学 (統計ライブラリー)
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

リサーチクエスチョン探し?データ分析?論文投稿?、、、で、もう悩まない!

第1章臨床研究ではなぜ統計が必要なのか?計画することの重要性
  • 推定ってどんなことをしているの?
  • 臨床研究を計画するってどういうこと?
  • どうにかして標本平均を母平均に近づけられないか?
第2章:研究目的をどれだけ明確にできるのかが重要
  • データさえあれば解析でどうにかなる、という考え方は間違い
  • 何を明らかにしたいのか? という研究目的が重要
  • 研究目的は4種類に分けられる
  • 統計専門家に相談する上でも研究目的とPICOを明確化しておく
第3章:p値で結果が左右される時代は終わりました
  • アメリカ統計協会(ASA)のp値に関する声明で指摘されていること
  • そうは言っても、本当に有意差がなくてもいいの…?
  • なぜ統計専門家はp値を重要視していないのか
  • 有意差がない時に「有意な傾向があった」といってもいい?
  • 統計を放置してしまうと非常にまずい
第4章:多くの人が統計を苦手にする理由
  • 残念ながら、セミナー受講だけで統計は使えません。
  • インプットだけで統計が使えない理由
  • どうやったら統計の判断力が鍛えられるか?
  • 統計は手段なので正解がないため、最適解を判断する力が必要
第5章:統計を使えるようになるために今日から何をすれば良いか?
  • 論文を読んで統計が使えるようになるための5ステップ
第6章:統計を学ぶために重要な環境
  • 統計の3つの力をバランスよく構築する環境

以下のボタンをクリックして、画面に出てくる指示に従って、必要事項を記入してください。

この記事を書いた人

統計 ER ブログ執筆者

元疫学研究者

統計解析が趣味

コメント

コメント一覧 (1件)

コメントする

目次