みずぎわブログ

技術系のことや日々に考えたことを書き連ねます

Rを使っての重回帰分析をggplotで図示しながらやる

手を動かしながら学ぶ ビジネスに活かすデータマイニングの勉強第2回

手を動かしながら学ぶ ビジネスに活かすデータマイニング

手を動かしながら学ぶ ビジネスに活かすデータマイニング

ggplotと格闘しつつ,きれいな図を作りながら勉強したのでその記録を残す.
今回は4章の重回帰分析を行った.

回帰分析

目的変数を説明変数で説明できるモデルを推定すること
例: アイスクリームの売上(目的変数) と 気温(説明変数)

y_i = \beta_0 + \beta{1i} x{1i} + \beta{2i} x{2i} + \cdots + \beta{ni} x{ni} + \epsilon_i

y : 目的変数
x : 説明変数
\beta : 偏回帰係数(説明変数の重み)
n: n番目の説明変数
i: i番目に測定されたデータ

\betaを求めることが重回帰分析の目的
\betaの正負,大きさで説明変数と目的変数の関係がわかる

オゾン濃度とその他要因の関係を調べる

元データ,月日は使わないので除外する.

> head(airquality)
  Ozone Solar.R Wind Temp Month Day
1    41     190  7.4   67     5   1
2    36     118  8.0   72     5   2
3    12     149 12.6   74     5   3
4    18     313 11.5   62     5   4
5    NA      NA 14.3   56     5   5
6    28      NA 14.9   66     5   6

> airq <- airquality[,1:4]
> head(airq)
  Ozone Solar.R Wind Temp
1    41     190  7.4   67
2    36     118  8.0   72
3    12     149 12.6   74
4    18     313 11.5   62
5    NA      NA 14.3   56
6    28      NA 14.9   66

ggplotで図示するためにmeltする

> mairq <- melt(airq)
> head(mairq)
  variable value
1    Ozone    41
2    Ozone    36
3    Ozone    12
4    Ozone    18
5    Ozone    NA
6    Ozone    28

んでこれだけではx軸の情報が表にないので追加する

> mairq$num <- c(1:153)
> head(mairq)
  variable value num
1    Ozone    41   1
2    Ozone    36   2
3    Ozone    12   3
4    Ozone    18   4
5    Ozone    NA   5
6    Ozone    28   6
.
.
154   Solar.R    NA   1
156   Solar.R    28   2
.
.

> p <- ggplot(mairq, aes(x=num, y=value, fill=variable, color=variable)) + geom_line()
> p

できた図がこれ

f:id:yusuke0h:20140907164918j:plain

他のバージョンで図示する.

> p + facet_grid(variable ~ .)
> p + facet_grid(variable ~ ., scales = "free_y")

f:id:yusuke0h:20140907164931j:plain

f:id:yusuke0h:20140907164937j:plain

各項目ごとに値がバラけている場合には分けてみると見やすい.
次に回帰分析lm()をやる.

> airq.lm <- lm(Ozone~., airq)

Ozoneを目的変数に説明変数は.(dot)
この意味を調べるとr - Meaning of ~. (tilde dot) argument? - Stack Overflowより,

The dot means "any columns from data that are otherwise not used". とデータフレームの中で他に使っていないカラムとのことである.
結果をそのまま,summary関数(詳細やまとめを表示する)を通してみると

> airq.lm

Call:
lm(formula = Ozone ~ ., data = airq)

Coefficients:
(Intercept)      Solar.R         Wind         Temp  
  -64.34208      0.05982     -3.33359      1.65209  

> summary(airq.lm)

Call:
lm(formula = Ozone ~ ., data = airq)

Residuals:
    Min      1Q  Median      3Q     Max 
-40.485 -14.219  -3.551  10.097  95.619 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept) -64.34208   23.05472  -2.791  0.00623 ** 
Solar.R       0.05982    0.02319   2.580  0.01124 *  
Wind         -3.33359    0.65441  -5.094 1.52e-06 ***
Temp          1.65209    0.25353   6.516 2.42e-09 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 21.18 on 107 degrees of freedom
  (42 observations deleted due to missingness)
Multiple R-squared:  0.6059,  Adjusted R-squared:  0.5948 
F-statistic: 54.83 on 3 and 107 DF,  p-value: < 2.2e-16

(Intercept): 切片 今回は負の切片を持つ
Solar.R : オゾンに対し正の相関を持つ 今回は0.06なのだがこれは大きいのだろうか小さいのだろうか?
Wind: オゾンに対し負の相関を持つ
Temp: オゾンに対し正の相関を持つ

まとめると,日照強度(Solar.R)と気温(Temp)が高いほどオゾン濃度(Ozone)が増し,
風速(Wind)が大きいほどオゾン濃度が下がることが判明した.

ビールの売上と花火,気温,CMの関係を調べる

元データとggplotでの図示

> head(beer)
   Revenue  CM Temp Firework
1 47.14347 141   31        2
2 36.92363 144   23        1
3 38.92102 155   32        0
4 40.46434 130   28        0
5 51.60783 161   37        0
6 32.87875 154   27        0

> mbeer <- melt(beer)
> mbeer$x <- c(1:30)
> head(mbeer)
  variable    value x
1  Revenue 47.14347 1
2  Revenue 36.92363 2
3  Revenue 38.92102 3
4  Revenue 40.46434 4
5  Revenue 51.60783 5
6  Revenue 32.87875 6

> p <- ggplot(mbeer, aes(x=x, y=value, fill=variable, color=variable)) + geom_line()
> p

f:id:yusuke0h:20140907165417j:plain

> p + facet_grid(variable ~ .)

f:id:yusuke0h:20140907165426j:plain

> p + facet_grid(variable ~ ., scales = "free_y")

f:id:yusuke0h:20140907165434j:plain

y軸をフリーにし,分けてみると見やすい.
花火は直接的に影響ありそうに見える.テレビCMも少しタイミングが遅れて関係しているように見える.
次に重回帰分析を行う.

> beer.lm <- lm(Revenue ~ ., beer)
> summary(beer.lm)

Call:
lm(formula = Revenue ~ ., data = beer)

Residuals:
   Min     1Q Median     3Q    Max 
-6.028 -3.038 -0.009  2.097  8.141 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) 17.23377   12.40527   1.389  0.17655    
CM          -0.04284    0.07768  -0.551  0.58602    
Temp         0.98716    0.17945   5.501    9e-06 ***
Firework     3.18159    0.95993   3.314  0.00271 ** 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 3.981 on 26 degrees of freedom
Multiple R-squared:  0.6264,  Adjusted R-squared:  0.5833 
F-statistic: 14.53 on 3 and 26 DF,  p-value: 9.342e-06

CMは小さな負の値,つまり薄い負の相関になっているが,図を見る限りタイミングが遅れて効果があるように見える. 重回帰分析は,直線的な予測をするモデルなので,タイミングの遅れには対応できないのかもしれない. このような場合にはCMの効果があるまでの間を把握し,データをもっと大きく区切ることが有効だと思う. 例えばCMの効果が出でるまでに3日かかるのであれば,1日単位のデータを結合して,3日単位のデータにすればいいと思う. この辺りはRでやるのは大変なのでスクリプト言語でやったほうが簡単だろう.

相関係数と重回帰分析

相関係数を求めて,図示する

> beercor <- cor(beer)
> beercor
             Revenue          CM       Temp    Firework
Revenue   1.00000000 -0.07355843 0.67461456  0.43715932
CM       -0.07355843  1.00000000 0.06244943 -0.12010466
Temp      0.67461456  0.06244943 1.00000000  0.04295698
Firework  0.43715932 -0.12010466 0.04295698  1.00000000
> mbeercor <- melt(beercor)
> mbeercor
         X1       X2       value
1   Revenue  Revenue  1.00000000
2        CM  Revenue -0.07355843
3      Temp  Revenue  0.67461456
4  Firework  Revenue  0.43715932
5   Revenue       CM -0.07355843
6        CM       CM  1.00000000
7      Temp       CM  0.06244943
8  Firework       CM -0.12010466
9   Revenue     Temp  0.67461456
10       CM     Temp  0.06244943
11     Temp     Temp  1.00000000
12 Firework     Temp  0.04295698
13  Revenue Firework  0.43715932
14       CM Firework -0.12010466
15     Temp Firework  0.04295698
16 Firework Firework  1.00000000

> p <- ggplot(mbeercor, aes(X1, X2)) + 
> geom_tile(aes(fill=value)) + 
> geom_text(aes(fill=value, label = round(value,3)),colour="white")
> p

f:id:yusuke0h:20140907165455j:plain

Revenueと他関数の関係は

             Revenue          CM       Temp    Firework
Revenue   1.00000000 -0.07355843 0.67461456  0.43715932

となる.
一方で正規化した重回帰分析の値は

> beer.lm$coefficients
(Intercept)          CM        Temp    Firework 
17.23377359 -0.04283877  0.98715569  3.18159007 

となる.
あれ? 結構値が違う気がするのだけど…教科書と違う…

なんにせよ,重回帰分析のほうが最小二乗法を使っているため正確らしい.