今回は、多変量解析の代表的な手法である回帰分析について解説する。
工学系や農学系の実験等を行う領域では頻繁に使用される手法であるが、 日常的な話題の中でも概念は広く利用されているので、取っ付き易い手法ではないだろうか。近年は機械学習等でも取り扱われていると思う。過去のデータからその構造を把握し、新規に測定されたデータに対する予測を 行ないたいと言うときに、回帰分析は有用である。 構造のシンプルな単回帰分析でこの手法の原理を理解し、 複数の説明変量を用いた重回帰分析に拡張する。 残差の取り方や、その二乗和を最少にするという考えは同じである。
散布図にもっともらしい「直線」を当てはめたい。
皆さんから収集した体格データを用いて、散布図を描いてみよう。どういう直線が「もっともらしい」と考えるか?
データに欠損値が含まれていると、後々の分析(残差プロット等)時に、 毎回欠損値を除去する手順を組み込む必要が生じて面倒なので、 分析対象の変量だけを先に切り出し、その上で、欠損値を除外(完全データ)しておく。
# データの切り出し
colnames(Student24)
## [1] "No" "Sex" "Height" "Weight" "Chest"
## [6] "Residence" "Remittance" "Carrier" "Fee"
StudTmp1<-Student24[,3:4] # 身長(3番目)と体重(4番目)だけを切り出す
StudTmp1[1:15,]
## Height Weight
## 1 145.0 38
## 2 145.5 42
## 3 146.7 41
## 4 148.0 42
## 5 148.0 43
## 6 148.9 NA
## 7 149.0 45
## 8 150.0 43
## 9 150.0 46
## 10 150.0 47
## 11 151.0 42
## 12 151.0 45
## 13 151.0 46
## 14 151.0 50
## 15 151.0 NA
dim(StudTmp1)
## [1] 792 2
元々の身長と体重のデータは 792例だったが、欠損値を含むデータが101例あり、 残ったのは691例である。
StudHW<-na.omit(StudTmp1) # 欠損値を含むデータを削除
dim(StudHW)
## [1] 691 2
colnames(StudHW)
## [1] "Height" "Weight"
StudHW[1:15,]
## Height Weight
## 1 145.0 38.0
## 2 145.5 42.0
## 3 146.7 41.0
## 4 148.0 42.0
## 5 148.0 43.0
## 7 149.0 45.0
## 8 150.0 43.0
## 9 150.0 46.0
## 10 150.0 47.0
## 11 151.0 42.0
## 12 151.0 45.0
## 13 151.0 46.0
## 14 151.0 50.0
## 16 151.7 41.5
## 17 152.0 35.0
以後は、Student24に代えて、欠損値を除去して完全データにしたStudHWを使って分析を行う。
【蛇足: パズルの要領で】上記では、欠損値を含むデータの例数を、101例=792-691として求めたが、 欠損値を含むデータの例数を直接的に数える式を作ってみると、例えば以下のようになる(他にも実現方法はあると思う)。 sum()関数は、本来は引数(カッコ内の式)の合計値を計算する関数だが、論理値 TRUE/FALSEの場合はTRUEを1、FALSEを0と捉えてその総数(=個数)を算出してくれる。 2通りの方法で実現してみたが、それぞれがどのように機能しているか理解できるであろうか? なお、コメントアウト(行頭に#を付けてある)行は確認のために変数の内容を表示させる行である。表示させたければ、行頭の#を削除すれば良い。
[実現方法1]
# 欠損値を含むデータの例数カウント(方法1)
StudTmp2<-!is.na(StudTmp1)
# StudTmp2[1:15,]
StudTmp3<-StudTmp2[,1] & StudTmp2[,2]
# StudTmp3[1:15]
# (StudTmp3==F)[1:15]
sum(StudTmp3==F)
## [1] 101
[実現方法2]
# 欠損値を含むデータの例数カウント(方法2)
StudTmp2<-is.na(StudTmp1)
# StudTmp2[1:15,]
StudTmp3<-StudTmp2[,1] | StudTmp2[,2]
# StudTmp3[1:15]
sum(StudTmp3) ## これと同じ意味 ===> sum(StudTmp3==T)
## [1] 101
回帰平面の方程式: \[ \textbf{y} = a + b \textbf{x} \]
測定値と予測値のズレ: \[ \varepsilon_{i} = y_{i} - (a+ b x_{i}) \;\;\;\;\;\; (i=1,2,...,n) \]
ズレの2乗の和を最小に: \[ S = \sum_{i=1}^{n}{\varepsilon_{i}^2} = \sum_{i=1}^{n} \{ {y_{i} - ( a + b x_{i}})\}^2 \;\;\; { \to min} \]
[余談] 回帰分析では「2乗和」を最小にすることを考えるが、「絶対値和」とか「符号付き和(1乗和)」を最小にする方法もアイディアとしてはあり得る。 2乗和だと式の展開が楽になる。
# 回帰分析(指定方法1)
RresultHW <- lm(Weight ~ Height,
data=StudHW) # 線形モデル, Linear Model
RresultHW # 簡略化した計算結果表示
##
## Call:
## lm(formula = Weight ~ Height, data = StudHW)
##
## Coefficients:
## (Intercept) Height
## -79.5566 0.8228
なお、以下のように記述しても同じ結果が得られる。 こちらの方が表記としては理解し易いかもしれないが、長くなるのが難点か。
# 回帰分析(指定方法2)
RresultTmp1 <- lm(StudHW$Weight ~ StudHW$Height,
data=StudHW) # 線形モデル, Linear Model
RresultTmp1 # 簡略化した計算結果表示
coef <-RresultHW$coefficient # 計算結果の取り出し(回帰係数)
coef # 回帰係数
## (Intercept) Height
## -79.5565674 0.8228171
resid <-RresultHW$residuals # 計算結果の取り出し(残差)
resid[1:20] # 残差(先頭の20例)
## 1 2 3 4 5 7
## -1.7519139 1.8366775 -0.1507030 -0.2203652 0.7796348 1.9568176
## 8 9 10 11 12 13
## -0.8659995 2.1340005 3.1340005 -2.6888166 0.3111834 1.3111834
## 14 16 17 18 19 20
## 5.3111834 -3.7647886 -10.5116337 -2.5116337 -1.5116337 -0.5116337
## 21 22
## -5.3344508 -4.3344508
plot(Weight ~ Height, data=StudHW,
xlab = "Height", ylab = "Weight",
main="Scatter Plot of Shintyou and Taijyuu") # 散布図の描画(これまでと別の指定方法)
abline(RresultHW) # 回帰直線を付加
abline(h=seq(40,100,10), lty=3)
abline(v=seq(140,190,5), lty=3)
回帰分析について、回帰係数以外にも知っておくべき情報がある。 それらは「summary(RresultHW)」の出力中に表示されている。
summary(RresultHW) # より詳細な計算結果表示
##
## Call:
## lm(formula = Weight ~ Height, data = StudHW)
##
## Residuals:
## Min 1Q Median 3Q Max
## -17.665 -4.671 -1.019 3.437 34.386
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -79.5566 6.1948 -12.84 <2e-16 ***
## Height 0.8228 0.0365 22.54 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 7.188 on 689 degrees of freedom
## Multiple R-squared: 0.4244, Adjusted R-squared: 0.4236
## F-statistic: 508.1 on 1 and 689 DF, p-value: < 2.2e-16
*以下、順に計算結果を見ていくと、
Adjusted R-squared: 0.4236
F-statistic: 508.1 on 1 and 689 DF, p-value: < 2.2e-16
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -79.5566 6.1948 -12.84 <2e-16 ***
Height 0.8228 0.0365 22.54 <2e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# 残差プロット: 対身長に対して
plot(StudHW$Height, RresultHW$residuals) # 残差プロット(対身長)
abline(v=seq(140,190,5),lty=3) # 点線を追記
abline(h=seq(-10,30,10),lty=3) # 点線を追記
abline(h=0,lty=1) # 原点を追記
# 残差プロット: 対体重に対して
plot(StudHW$Weight, RresultHW$residuals) # 残差プロット(対体重)
abline(v=seq(30,100,5),lty=3) # 点線を追記
abline(h=seq(-10,30,10),lty=3) # 点線を追記
abline(h=0,lty=1) # 原点を追記
# 残差のヒストグラム
hist(RresultHW$residuals, right=F)
abline(h=seq(0,200,25),lty=3) # 点線を追記
# 残差の箱ひげ図
boxplot(RresultHW$residuals, horizontal=T)
abline(v=seq(-10,30,10),lty=3) # 点線を追記
# 残差のQQプロット: 正規確率プロット
qqnorm(RresultHW$residuals) # QQプロット(正規確率プロット)
qqline(RresultHW$residuals, lty=2) # 基準線の描画
abline(h=0, lty=1) # 実線を追記
abline(v=0, lty=1) # 実線を追記
abline(h=seq(-10,30,10),lty=3) # 点線を追記
対象になったのは 691名。
測定精度上回る計算結果は表示させることはできても、意味はない。
プログラムの出力をそのまま書き写さないように。
[重要な注意]
統計ソフトは単なる道具。使いこなすのは各自。
67.8 <=== 67.75~67.84
68 <=== 67.5 ~68.4
[例2] 日本の観測史上の最高気温は、
2018(平成30)年7月23日に熊谷市で観測された41.1度であり、
最低気温は、1902(明治35)年1月25日に北海道旭川市の-41度であった。===>
-41.0度
[例3]
2001年のイチロー選手の打率は3割5分であった。
2006年は3割3分1厘であった。===> 3割5分0厘
このページで取り扱ったプログラムだけを抜き出して以下に列挙しておく。
## 1.1. アイディア
tmpRand<-rnorm(2000)
tmpRand[1:40]
StudTmp<-Student24
StudTmp$Height <-Student24$Height+tmpRand[1:772]*0.2
StudTmp$Weight <-Student24$Weight+tmpRand[1001:1772]*0.2
# 乱数で位置をずらした散布図
plot(StudTmp$Height, StudTmp$Weight,
xlab = "Height", ylab = "Weight",
main="Scatter Plot of Shintyou and Taijyuu")
abline(h=seq(40,100,10), lty=3)
abline(v=seq(140,190,5), lty=3)
## # 元データそのものの散布図(点が重なって判読できない)
## plot(Student24$Height, Student24$Weight)
## abline(h=seq(40,100,10), lty=3)
## abline(v=seq(140,190,10), lty=3)
RresultTmp <- lm(Weight ~ Height, data=StudTmp)
## RresultTmp
## summary(RresultTmp)
plot(Weight ~ Height, data=StudTmp,
xlab = "Height", ylab = "Weight",
main="Scatter Plot of Shintyou and Taijyuu")
abline(RresultTmp)
abline(h=seq(40,100,10), lty=3)
abline(v=seq(140,190,5), lty=3)
## 1.2. 前準備(Rでの利用に際して)
# データの切り出し
colnames(Student24)
StudTmp1<-Student24[,3:4] # 身長(3番目)と体重(4番目)だけを切り出す
StudTmp1[1:15,]
dim(StudTmp1)
StudHW<-na.omit(StudTmp1) # 欠損値を含むデータを削除
dim(StudHW)
colnames(StudHW)
StudHW[1:15,]
# 欠損値を含むデータの例数カウント(方法1)
StudTmp2<-!is.na(StudTmp1)
# StudTmp2[1:15,]
StudTmp3<-StudTmp2[,1] & StudTmp2[,2]
# StudTmp3[1:15]
# (StudTmp3==F)[1:15]
sum(StudTmp3==F)
# 欠損値を含むデータの例数カウント(方法2)
StudTmp2<-is.na(StudTmp1)
# StudTmp2[1:15,]
StudTmp3<-StudTmp2[,1] | StudTmp2[,2]
# StudTmp3[1:15]
sum(StudTmp3) ## これと同じ意味 ===> sum(StudTmp3==T)
## 2.1. 定式化
# 回帰分析の表記方法(その1)
RresultHW <- lm(Weight ~ Height,
data=StudHW) # 線形モデル, Linear Model
RresultHW # 簡略化した計算結果表示
# 回帰分析の表記方法(その2)
RresultTmp1 <- lm(StudHW$Weight ~ StudHW$Height,
data=StudHW) # 線形モデル, Linear Model
RresultTmp1 # 簡略化した計算結果表示
coef <-RresultHW$coefficient # 計算結果の取り出し(回帰係数)
coef # 回帰係数
resid <-RresultHW$residuals # 計算結果の取り出し(残差)
resid[1:20] # 残差(先頭の20例)
# 散布図に回帰直線を付加する方法
plot(Weight ~ Height, data=StudHW,
xlab = "Height", ylab = "Weight",
main="Scatter Plot of Shintyou and Taijyuu") # 散布図の描画(これまでと別の指定方法)
abline(RresultHW) # 回帰直線を付加
abline(h=seq(40,100,10), lty=3)
abline(v=seq(140,190,5), lty=3)
## 3. その他の重要な情報
summary(RresultHW) # より詳細な計算結果表示
## 4. 残差分析もお忘れなく
# 残差プロット: 対身長に対して
plot(StudHW$Height, RresultHW$residuals) # 残差プロット(対身長)
abline(v=seq(140,190,5),lty=3) # 点線を追記
abline(h=seq(-10,30,10),lty=3) # 点線を追記
abline(h=0,lty=1) # 原点を追記
# 残差プロット: 対体重に対して
plot(StudHW$Weight, RresultHW$residuals) # 残差プロット(対体重)
abline(v=seq(30,100,5),lty=3) # 点線を追記
abline(h=seq(-10,30,10),lty=3) # 点線を追記
abline(h=0,lty=1) # 原点を追記
# 残差のヒストグラム
hist(RresultHW$residuals, right=F)
abline(h=seq(0,200,25),lty=3) # 点線を追記
# 残差の箱ひげ図
boxplot(RresultHW$residuals, horizontal=T)
abline(v=seq(-10,30,10),lty=3) # 点線を追記
# 残差のQQプロット: 正規確率プロット
qqnorm(RresultHW$residuals) # QQプロット(正規確率プロット)
qqline(RresultHW$residuals, lty=2) # 基準線の描画
abline(h=0, lty=1) # 実線を追記
abline(v=0, lty=1) # 実線を追記
abline(h=seq(-10,30,10),lty=3) # 点線を追記