ラベル 共分散 の投稿を表示しています。 すべての投稿を表示
ラベル 共分散 の投稿を表示しています。 すべての投稿を表示

2012/09/19

文系のための「二変数の関係」(3)

これまでの話から、二つの変数間の関係を見るための方法には、
相関係数以外にも単回帰という方法があることが理解できたハズ。

単回帰は、相関係数に良く似ているが、
一方の変数によってもう一方を説明するという考え方に基づいている。
相関係数は、二つの変数を平等に見ていたので、この点が大きく異なる。

また、重要なこととして、相関係数は二つの変数が平等なので軸は関係無いが、
単回帰の場合は、どちらを説明変数に置くかによって値が異なる。
まぁ、この辺りは、感覚的に理解できていることだろうと信じたい。

さて、今回は、もう少し単回帰について踏み込んでみる。
実は、前回の話では、二つの変数間の関係の強さについては、
十分に検討ができていなかったのである。

相関係数と同様に、二つの変数間の関係の強さを観察するには、
推定された値と実際の値との誤差の部分の解釈が必要となる。
本日は、このことについて整理する。

ということで、前回のデータの読み込みから。

# Windows と Linux の人は次のコマンド
X <- read.table("clipboard", sep=",", header=TRUE)

# Mac の人は次のコマンド
X <- read.table(pipe("pbpaste") , sep=",", header=TRUE)

以下が、そのデータ。データの説明に関しては、平均の話を参照。

Oroshi_Kg, Taka, Naka, Yasu
Tai, 1336, 3150, 1217, 53
Chinu, 226, 630, 513, 105
Sawara, 212, 1575, 1259, 840
Yazu, 4834, 840, 315, 179
Suzuki, 618, 1575, 1146, 525
Akou, 21, 4725, 3129, 1575
Kochi, 28, 2100, 874, 210
Okoze, 28, 5250, 2635, 210
Ainame, 29, 3150, 621, 315
Hage, 1205, 1890, 383, 210
Konoshiro, 21, 2100, 1100, 105
Sayori, 12, 5250, 3916, 1260
Anago, 1637, 2625, 1721, 630
Mebaru, 330, 4200, 1680, 315
Tachiuo, 1211, 2310, 930, 105
Hamo, 1622, 3938, 592, 53
Karei, 41, 6300, 3178, 525
Hirame, 540, 2100, 1496, 210
Aji, 5149, 3150, 789, 210
Saba, 5413, 3675, 625, 53
Ika, 2414, 2888, 1083, 105
Tako, 1844, 1890, 1180, 525
Ebi, 560, 7350, 1420, 525
KurumaEbi, 222, 8925, 6508, 2625
Koiwashi, 1316, 1155, 617, 328
ObaIwashi, 2716, 499, 267, 175
Mentai, 678, 1155, 859, 394
Hamachi, 4772, 998, 632, 105
Isaki, 268, 2625, 1465, 840

ふむ。前回と同様に、中値安値の関係を使うことにするか。
単回帰分析も行うことにしよう。lm()関数があるが今は使わない。

x1 <- X$Naka
x2 <- X$Yasu

# まず、推定値を求める
B <- cov(x1,x2)/var(x1)

# まず、推定値を求める
B0 <- mean(x2) - B*mean(x1)

# x2の推定値を求める
x2.hat <- B0 + B*x1

数式あった方が解り易い。x1によってx2の値を説明するので、
たしか、以下のような式になるハズであった。



ここで、二つ推定値のいうのがそれぞれ、

,  

であった。詳しい説明は既にしてあるから、ここまでは大丈夫であろう。
自信が無い人は、もう一度復習をすること。

さて、現在、この回帰式によって説明されるのは、
あくまで、理屈として推定される値であって、実際の値とは異なる
理屈上の話だから、直線で推定の直線が描けたのであった。

では、実際の値というのは、推定された値を使ってどのように表現できるか?



この式は、推定値では無くて、実際の値を表しているから、
左辺の「^(ハット)」が取れていることにも注目。

さて、この式の中で重要なことは最後に「」の値が付いていること。
これを「残差(residuals)」と呼び、この記号は一般的に残差を表す。

つまり、推定された値に誤差を加えたものが実際の値、と考えるのである。
この辺りの考え方は、数学嫌いの人には、少々、理解し難いかもしれない。

では、残差は、どうすれば求めることができるか?
これも中学校までの数学の知識があれば簡単なことであろう。



つまり、実際の値から推定値を引くだけ。混乱することは無い。
では、早速、この誤差の部分を計算してみる。

residuals <- x2 - x2.hat

ふむ。これで誤差が計算できた。ちょっと解りにくいので可視化する。
# 上手く重なるようにx軸とy軸の描画範囲を固定する
x.lim <- c(0,max(x1))
y.lim <- c(0,max(x2))

# 散布図を作成する
plot(x1, x2, xlim=x.lim, ylim=y.lim, pch=16)

# 図を重ねるためのオマジナイ
par(new=TRUE)

# xの値の範囲を最低値と最大値で決める。
x1.range <- seq(min(x1),max(x1))

# x値の範囲に対応する推定値を計算する。
x1.estim <- B0 + B*x1.range

# 回帰直線を引く
plot(x1.range, x1.estim, xlim=x.lim, ylim=y.lim, xaxt="n", yaxt="n", xlab="", ylab="", type="l", col="red")

# 残差を表す線を描画する
for(i in seq(1,length(x1))){
  x <- rep(x1[i],2)                 # x1の値を2つ作る
  y <- c(x2[i], x2[i]-residuals[i]) # x2の値とx2の値から残差を引いた値を作る

  # 残差を表す垂線を引く
  par(new=TRUE)
  plot(x, y, xlim=x.lim, ylim=y.lim, xaxt="n", yaxt="n", xlab="", ylab="", type="l", col="blue")
}

# 最後にグリッドを描いて全体を整える
grid()

この図において、実際の値から回帰直線に引かれた垂線が残差「residuals」である。
この残差というのが、二つの変数間の関係を観察する上で重要な値で、
残差を合わせた値が小さいほど当てはまりが良いことを表す



二乗しているのは、値の正負が打ち消し合わないようにするため。
これを残差平方和(Sum Squared Error)と呼ぶ。とりあえず、Se と置いておく。
試しに、今回のデータを使って、この値を確認してみる。

(se <- sum(residuals^2))

これを実行すると、以下のようになる。

> (se <- sum(residuals^2))
[1] 2076206

さて、この値が小さいということが重要なのだけれど、これは大きいのか?
この値の大小の程度を見分けるためには、やはり、基準化しないといけない。
原点に帰って、もう一度、この残差というものが何なのかを考えてみる。

データを観察する上で、最も重要なのは、くどいけれど、バラツキ
そして、個々の値のバラツキ偏差と言い、
偏差を二乗して足し合わせたものが偏差平方和

とりあえず、目的変数総平方和(Sum Squared Total Deviation)と呼び、
この値をSt とでも置いておくことにする。式は以下の通り。



これを対象数から1を引いた「n-1」で割ると?そうそう、分散になる。
要するに、分散の式の分子の部分に当たるのであった。

さて、このStSeの関係に注目してやると、
Stは観測値のバラツキの平方和で、Seは残差のバラツキの平方和だから、
予測値のバラツキとSe を足したものが、St になるはず。

では、予測値のバラツキはどうなるか?というと、以下のようになる。



つまり、St = Se + Sr という関係が成立するはず。
これは、直感的に理解できる。ここからが数学マジック!
両辺をStで割るとどういうことになるのか?



となる。ここで、残差平方和の影響の大きさを見たいので、
この式から、予測値のバラツキの部分を抜いてしまう。
すると、以下のようになる。左辺に何もないと困るので「」を置いておく。



つまり、残差平方和の大きさというのは、このように表すことができる。
この値が「1」に近づくということは、残差の影響が小さいことを意味する
なかなか、エレガントな数式。私は美しいと思うのだが、どうだろう?

さて、この「」という指標は頻繁に登場する。だからちゃんと名前がある。
一般的に、この指標のことを「決定係数」と呼び、慣例的に「」で表す。

では、この決定係数を実際に計算してみる。

# 一応、三つの値を出しておく。
st <- sum((x2-rep(mean(x2), length(x2)))^2)
sr <- sum((x2.hat-rep(mean(x2), length(x2)))^2)
se <- sum((x2-x2.hat)^2)

# 決定係数の計算
(R2 <- 1-(se/st))

では、確認。以下が実行結果。

> # 決定係数の計算
> (R2 <- 1-(se/st))
[1] 0.7576962

さて、この結果は果たして高いと言えるのかどうか?実は、判断は難しいのであるが、
一方の変数がもう一方を説明する上で、75.8%の説明力を持っていることを示していて、
これは、決して低い値ではない。大体、60〜70%以上であれば、悪くはない。

決定係数に関しては、注意するべきことがある。
相関係数と同様に、この値を盲目的に信用してはならないし、
慎重にデータの解釈をしなければならない。決定係数は、基準の一つでしかない

例えば、決定係数は、対象数が多くなると必然的に値が高くなるので、
自由度調整済み決定係数と呼ばれる指標を用いたり、
確立統計の手法を用いる場合もある。

さてさて、最後に、Rのlm()関数を使った場合についてもやっておく。
とりあえず、X.reg という変数に、回帰分析の結果を入れて、その要約を確認する。

X.reg <- lm(x2 ~ x1)
summary(X.reg)

以下がこの処理の実行結果。

> X.reg <- lm(x2 ~ x1)
> summary(X.reg)

Call:
lm(formula = x2 ~ x1)

Residuals:
    Min      1Q  Median      3Q     Max 
-678.72 -163.58   -7.29  158.81  506.60 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept) -69.68447   77.21191  -0.903    0.375    
x1            0.36372    0.03958   9.189 8.45e-10 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1 

Residual standard error: 277.3 on 27 degrees of freedom
Multiple R-squared: 0.7577, Adjusted R-squared: 0.7487 
F-statistic: 84.43 on 1 and 27 DF,  p-value: 8.447e-10 

実は、色々と見ないといけないのであるが、
そもそも、今回の話の目的は、二つの変数間の関係を見ることであって、
精密な推定を行うことではない。ということで、決定係数以外は無視。

さて、上記の出力において、Coefficients の部分は係数の部分。
決定係数の部分は、下から二行目の部分。Multiple R-squared の右側。
ちゃんと、手計算で算出した決定係数と一致していることが解る。

回帰分析の解説の多くは、「目的変数説明変数によって推定する手法」、
と紹介しているのではないかと思うが、変数間の関係を見ることが重要なのである。
これは、相関係数の考え方に非常に良く似ているのである。たしかに、式も似ていた。

相関係数との違いは、一方の変数によってもう一方の変数を説明するという考え方
したがって、その説明力を「残差」に注目して検討するのである
残差が小さいほど、二つの変数の間の関係は強いということになる。

他の教科書に書かれているように、推定に注目するのであれば、
より複雑なことが必要になるし、3つ以上の変数間の関係になると結構大変。
残差そのものに関する検討や、複数の変数の当てはまりの高さの検討も必要。

この章で書いてしまいたい話ではあるが、
この辺りの話は、中級編重回帰分析の話で整理することにする。

2012/09/05

文系のための「主成分分析の仕組み」(2)

前回は、特異値分解を通して主成分分析の仕組みについて整理した。
主成分分析は、「対象の本質」と「変数の本質」に分離し、
対象のみに焦点」を当てて分析する方法だった。

そして、対象の本質のみを記述した部分を主成分得点と呼び、
変数の本質のみを記述した部分を主成分負荷量と呼んだ。

また、対象のみの状態にすることで、変数間の関係から開放され、
分散のみに注目するだけで良い状況になった。

前回の話では、特異値分解を用いて主成分分析を行ったが、
もちろん、Rには主成分分析の関数が存在している。しかも、色々。

そこで、今回は最初にRにおける主成分分析関数を使ってみることにする。

今回もGoogle Spreadsheet にデータを置いてあるので、それを利用する。

library(RCurl)

データの詳細は、散布図行列の話にあるので、そちらを参照する。
ライブラリを無事に読み込めたら、次は、以下のコマンドを実行する。

# Google Spreadsheet からデータをダウンロードする
data <- getURL("https://docs.google.com/spreadsheet/pub?key=0AtOtIs5BjRVhdHo0c0pjb29OTU9aV3BmQUFJUWJQa0E&single=true&gid=0&range=A1%3AK48&output=csv")

# ダウンロードしたデータを読み込む
X <- as.matrix(read.table(textConnection(data), header=TRUE, row.names=1, sep=","))

まずは、分散共分散行列相関係数行列散布図行列を確認する。
毎回、これらを確認することを忘れてはいけない。
# 散布図行列を作成するためにpsych ライブラリを読み込む。
library(psych)

# 分散共分散行列を出す
round(cov(X), 3)

# 相関係数行列を出す
round(cor(X), 3)

#  散布図行列を出す。
pairs.panels(X, scale=TRUE, smooth=FALSE, ellipses=FALSE, density=FALSE)

分散共分散行列と相関係数行列の出力結果は以下の通り。

> # 散布図行列を作成するためにpsych ライブラリを読み込む。
> library(psych)
>
> # 分散共分散行列を出す
> round(cov(X), 3)
         HM    ELD      HC    CHR     SC     LI     SP    ENV    DIS      IC
HM   27.370  0.750   5.470 -2.063  7.600  2.305 -5.029  5.586 -1.925 -12.463
ELD   0.750 38.669  22.176 10.859 -2.048  9.253  4.594 16.180 -0.199  44.576
HC    5.470 22.176 103.638 11.745  6.029  9.985  3.673 12.545 -0.205  64.775
CHR  -2.063 10.859  11.745 13.820 -0.021  7.465  8.619 12.185  0.559  11.328
SC    7.600 -2.048   6.029 -0.021 52.300 -2.108  0.040  1.468  1.434   7.519
LI    2.305  9.253   9.985  7.465 -2.108 12.677  5.382 20.473  0.950   0.394
SP   -5.029  4.594   3.673  8.619  0.040  5.382 21.932 12.175  1.550  13.332
ENV   5.586 16.180  12.545 12.185  1.468 20.473 12.175 58.090  0.927  -2.488
DIS  -1.925 -0.199  -0.205  0.559  1.434  0.950  1.550  0.927  7.540  12.452
IC  -12.463 44.576  64.775 11.328  7.519  0.394 13.332 -2.488 12.452 279.265
>
> # 相関係数行列を出す
> round(cor(X), 3)
        HM    ELD     HC    CHR     SC     LI     SP    ENV    DIS     IC
HM   1.000  0.023  0.103 -0.106  0.201  0.124 -0.205  0.140 -0.134 -0.143
ELD  0.023  1.000  0.350  0.470 -0.046  0.418  0.158  0.341 -0.012  0.429
HC   0.103  0.350  1.000  0.310  0.082  0.275  0.077  0.162 -0.007  0.381
CHR -0.106  0.470  0.310  1.000 -0.001  0.564  0.495  0.430  0.055  0.182
SC   0.201 -0.046  0.082 -0.001  1.000 -0.082  0.001  0.027  0.072  0.062
LI   0.124  0.418  0.275  0.564 -0.082  1.000  0.323  0.754  0.097  0.007
SP  -0.205  0.158  0.077  0.495  0.001  0.323  1.000  0.341  0.121  0.170
ENV  0.140  0.341  0.162  0.430  0.027  0.754  0.341  1.000  0.044 -0.020
DIS -0.134 -0.012 -0.007  0.055  0.072  0.097  0.121  0.044  1.000  0.271
IC  -0.143  0.429  0.381  0.182  0.062  0.007  0.170 -0.020  0.271  1.000

前回は、svd()関数を使って主成分分析を行った。まずは、その復習。
偏差行列を出す処理は簡略化。まとめて実行。

# 行列の引き算ができるように、平均値を総数個複製する。
M <- matrix(rep(m <- t(colMeans(X)), each=nrow(X)), nrow=nrow(X))

# 元の行列から、偏差行列を作成する。
A <- as.matrix(X-M)

# 特異値分解を行う
A.svd <- svd(A)

# 主成分スコアと主成分負荷量を計算する
A.svd.score <- A.svd$u %*% diag(A.svd$d)
A.svd.loadings <- A.svd$v %*% diag(A.svd$d)

これで主成分分析は完了。主成分得点主成分負荷量が出せた。
今回は、この結果とRの主成分分析の関数との比較するところから始める。

実は、Rの主成分分析の関数は一つではなく複数存在し、少しずつ異なる
R の関数は、世界中の大多数の研究者、技術者、学生らによって開発されているので、
様々な手法が存在し得る。そのあたりが、商用製品と大きく異なるところ。

雑多という批判を受けることもあるが、中身がはっきりと見えるし、
問題があれば自分で修正もできる。自分で開発した関数を公開することもできる。
それゆえに、従来の商用製品よりも信頼性は高いと言われている。

さて、話は少し逸れたが、有名な主成分分析の関数は以下の通り。
  • princomp()関数:stats パッケージの主成分分析の関数。そのまま使える。
  • prcomp()関数:同じく、stats パッケージの主成分分析の関数。そのまま使える。
  • PCA()関数FactoMineR パッケージの主成分分析の関数。インストールが必要
では、これらの内、どれを使うべきか?難しい問題である。

princomp()関数は、色々と問題があって使うべきではない
prcomp()関数は、理論通りの方法。ただし、バイプロットと呼ばれる図では注意が必要。
PCA()関数は、非常に多機能。ただし、色々と値が調整されているので注意が必要。

とりあえずは、最も無難そうなprcomp()関数を使うことにする。

# prcomp()関数で主成分分析を行い、変数に格納する。
X.pca <- prcomp(X)

# 分析結果の格納状態を確認する。
str(X.pca)

結果がどのように格納されているかというと以下の通り。

> str(X.pca)
List of 5
 $ sdev    : num [1:10] 17.68 10.04 8.1 7.32 5.32 ...
 $ rotation: num [1:10, 1:10] 0.0341 -0.1811 -0.3131 -0.0574 -0.0318 ...
  ..- attr(*, "dimnames")=List of 2
  .. ..$ : chr [1:10] "HM" "ELD" "HC" "CHR" ...
  .. ..$ : chr [1:10] "PC1" "PC2" "PC3" "PC4" ...
 $ center  : Named num [1:10] 13.8 32.3 26.6 19.8 41.9 ...
  ..- attr(*, "names")= chr [1:10] "HM" "ELD" "HC" "CHR" ...
 $ scale   : logi FALSE
 $ x       : num [1:47, 1:10] 3.65 19.79 4.19 -17.59 -4.17 ...
  ..- attr(*, "dimnames")=List of 2
  .. ..$ : chr [1:47] "Hokkaido" "Aomori-ken " "Iwate-ken " "Miyagi-ken" ...
  .. ..$ : chr [1:10] "PC1" "PC2" "PC3" "PC4" ...
 - attr(*, "class")= chr "prcomp"

では、特異値分解で行った方法と順番に比較する。
今回は、長くなるので出力だけ。出力が同じであることが確認できれば良い。
  • $ sdev は、主成分得点標準偏差
> # prcomp()関数の$sdev の中身
> X.pca$sdev
 [1] 17.678171 10.038151  8.099573  7.317139  5.324851  4.775684  3.889277
 [8]  2.695817  2.462664  1.804632

> # 特異値分解の場合。エラーが出るがここでは無視。
> sd(A.svd.score)
 [1] 17.678171 10.038151  8.099573  7.317139  5.324851  4.775684  3.889277
 [8]  2.695817  2.462664  1.804632
  • $ rotation は、特異値ベクトル「V」のこと。つまり、「変数の本質の回転
> # prcomp()関数の$rotation の中身、長いので一部のみ。
> head(round(X.pca$rotation, 3))
       PC1    PC2    PC3    PC4    PC5    PC6    PC7    PC8    PC9   PC10
HM   0.034 -0.146  0.116 -0.220 -0.724  0.294 -0.544  0.063 -0.009 -0.063
ELD -0.181 -0.233 -0.245  0.055 -0.352 -0.807  0.005 -0.114 -0.247 -0.029
HC  -0.313 -0.673  0.598  0.244  0.141  0.065  0.037 -0.038 -0.066 -0.028
CHR -0.057 -0.181 -0.156  0.006  0.188 -0.220 -0.267  0.523  0.616 -0.364
SC  -0.032 -0.054  0.275 -0.915  0.176 -0.204  0.089 -0.006  0.012  0.059
LI  -0.021 -0.244 -0.213 -0.006 -0.012  0.038  0.000  0.384  0.072  0.860

> # 特異値分解の場合。名前は入ってないが同じ。
> head(round(A.svd$v,3))
       [,1]   [,2]   [,3]   [,4]   [,5]   [,6]   [,7]   [,8]   [,9]  [,10]
[1,]  0.034 -0.146  0.116 -0.220 -0.724  0.294 -0.544  0.063 -0.009 -0.063
[2,] -0.181 -0.233 -0.245  0.055 -0.352 -0.807  0.005 -0.114 -0.247 -0.029
[3,] -0.313 -0.673  0.598  0.244  0.141  0.065  0.037 -0.038 -0.066 -0.028
[4,] -0.057 -0.181 -0.156  0.006  0.188 -0.220 -0.267  0.523  0.616 -0.364
[5,] -0.032 -0.054  0.275 -0.915  0.176 -0.204  0.089 -0.006  0.012  0.059
[6,] -0.021 -0.244 -0.213 -0.006 -0.012  0.038  0.000  0.384  0.072  0.860
  • $ center というのは、元のデータの真ん中。列平均値特異値分解とは無関係
> # prcomp()関数の$center の中身。長いので一部のみ。
> round(X.pca$center ,3)
    HM    ELD     HC    CHR     SC     LI     SP    ENV    DIS     IC
13.804 32.349 26.585 19.849 41.885 12.053 16.532 24.983  7.028 25.081

> # 特異値分解とは無関係。元データの列平均。
> round(colMeans(X), 3)
    HM    ELD     HC    CHR     SC     LI     SP    ENV    DIS     IC
13.804 32.349 26.585 19.849 41.885 12.053 16.532 24.983  7.028 25.081
  • $ scale なんだ、コレ!? 実は、これが今日の話のメインに関係説明は後回し
> # prcomp()関数の$scale の中身。とりあえず、中身の確認だけ。
> X.pca$scale
[1] FALSE
  • $ x これは、主成分得点
> # prcomp()関数の$x の中身。長いので一部のみ。
> head(round(X.pca$x ,3)[,1:5])
                 PC1    PC2    PC3     PC4    PC5
Hokkaido       3.651 -7.957  5.140   1.052  2.310
Aomori-ken    19.786  5.058 12.888 -11.767  0.633
Iwate-ken      4.191 18.646 -4.698   7.407  3.635
Miyagi-ken   -17.588 -1.574  2.599  -2.082 -9.318
Akita-ken     -4.172 16.770 10.396   3.749  6.742
Yamagata-ken  21.314 14.733  1.865   9.510  1.088

> # 特異値分解の場合。名前は入ってないが同じ。
> head(round(A.svd.score,3)[,1:5])
        [,1]   [,2]   [,3]    [,4]   [,5]
[1,]   3.651 -7.957  5.140   1.052  2.310
[2,]  19.786  5.058 12.888 -11.767  0.633
[3,]   4.191 18.646 -4.698   7.407  3.635
[4,] -17.588 -1.574  2.599  -2.082 -9.318
[5,]  -4.172 16.770 10.396   3.749  6.742
[6,]  21.314 14.733  1.865   9.510  1.088

以上のように、prcomp()関数は、特異値分解によって主成分分析をしていることが解る。
なお、主成分負荷量に関しては計算されておらず、
主成分プロット負荷量をプロットする際に内部的に計算される

さて、後回しにしていたが、唯一、なかったものが $ scale の部分だった。
これは一体、何だろうか?scale という言葉に見覚えは無いだろうか?
そうそう。確か、標準化のことを scaling と呼んだ。平均「0」で分散「1」

実は、主成分分析は、分散共分散行列に対応させる方法と、
相関係数行列に対応させる方法の二種類の方法が存在する。

なぜか?よく考えてみると難しい話ではない。

要するに、各変数の単位同じ場合異なる場合があって、
単位が異なる場合には、全体的に大きな値の入った変数に影響されるから

例えば、身長、体重、血圧、体温という変数があるデータがあったとする。
このとき、身長をミリ体重をキロ血圧をパスカル体温を摂氏
でそれぞれ計測していたとする。つまり、単位がバラバラの状況

この状況というのは、実は、別の単位で置き換えることもできる。
身長をメートル体重をグラム血圧をミリ体温を華氏、といった具合に。

この二つのデータは、単位が変わっただけで、本質的には何も変わらないが、
分散共分散行列の結果は、値に応じて変わってしまう
一方、相関係数行列の場合は、平均と分散で調整しているため結果は同じ。

つまり、相関係数行列に対応するように主成分分析を行うことで、
単位の問題を解決することができる

また、単位そのものが一緒であっても、変数間の値の差が明らかに大きい場合で
かつ、そういった状況が望ましくないような場合には、
相関係数行列に対応した方法の方が適することがある

さて、では、実際に相関係数行列に対応した方法を検討してみる。

# 偏差行列の代わりに、標準化したデータを用いる
Z <- scale(X)

# 特異値分解を行う
Z.svd <- svd(Z)

# 主成分得点と主成分負荷量を変数に格納する
Z.svd.score <- Z.svd$u %*% diag(Z.svd$d)
Z.svd.loadings <- Z.svd$v %*% diag(Z.svd$d)

# 主成分得点の一部を表示する
head(round(Z.svd.loadings, 3)[,1:5])

この結果を、prcomp()関数と比較する。

# prcomp()関数のscaleパラメータをTRUEに変更する。
prcomp(X, scale=TRUE)

# 主成分得点の一部を表示する。
head(round(X.pca$x ,3)[,1:5])

標準化された行列で特異値分解をした結果とprcomp()関数の出力結果を比較する。

> head(round(Z.svd.score,3)[,1:5])
       [,1]   [,2]   [,3]   [,4]   [,5]
[1,] -0.595  0.260  0.268  0.518 -0.520
[2,]  3.213  0.435  1.089 -1.717  0.079
[3,]  1.798 -1.489 -2.021 -0.433  1.478
[4,] -1.161 -1.124  1.607 -1.371  2.359
[5,]  2.841 -2.078 -0.574 -0.500  0.656
[6,]  2.837 -0.149 -1.400  1.052  0.369

> # 主成分得点の一部を表示する。
> head(round(X.pca$x ,3)[,1:5])
                PC1    PC2    PC3    PC4    PC5
Hokkaido     -0.595  0.260  0.268  0.518 -0.520
Aomori-ken    3.213  0.435  1.089 -1.717  0.079
Iwate-ken     1.798 -1.489 -2.021 -0.433  1.478
Miyagi-ken   -1.161 -1.124  1.607 -1.371  2.359
Akita-ken     2.841 -2.078 -0.574 -0.500  0.656
Yamagata-ken  2.837 -0.149 -1.400  1.052  0.369

このように、データを標準化した結果と同じなり、
変数間の単位の差は、調整されている

ところで、主成分分析の結果として出力される分散は、
元の行列の分散共分散特異値に対応するのだった。

また、データを標準化したデータの分散共分散行列は、
相関係数行列に一致するのだった。

# 分散共分散に対応する主成分の分散
round(svd(cov(X))$d, 3)

# 相関係数行列に対応する主成分の分散
round(svd(cor(X))$d, 3)

# prcomp()関数の場合。確か、標準偏差の二乗が分散だった。
round((X.pca$sdev)^2, 3)

以下が、上記の実行結果。


> # 分散共分散に対応する主成分の分散
> round(svd(cov(X))$d, 3)
 [1] 312.518 100.764  65.603  53.541  28.354  22.807  15.126   7.267   6.065   3.257

> # 相関係数行列に対応する主成分の分散
> round(svd(cor(X))$d, 3)
 [1] 3.012 1.507 1.349 1.100 0.872 0.629 0.569 0.468 0.295 0.198

> # prcomp()関数の場合。確か、標準偏差の二乗が分散だった。
> round((X.pca$sdev)^2, 3)
 [1] 3.012 1.507 1.349 1.100 0.872 0.629 0.569 0.468 0.295 0.198


さて、相関係数行列に対応する主成分分析を行った場合、
出てきた分散は、非常に面白い性質を持っている。

# とりあえず、平均を取ってみる。
mean(svd(cor(X))$d)

そして、その実行結果。


> mean(svd(cor(X))$d)
[1] 1


平均は「1」標準化は、平均が「0」で分散が「1」となるような調整であったので、
当然、分散の平均は「1」となるのであるが、個々の値を見ると「1」以上のものもある

このことから、主成分分析を行うと、元の分散を個々の再配分していることが解る。

さて、今回は、サンプルデータを用いて、
分散共分散行列相関係数行列の二つの状況に対応する主成分分析を行ったが、
用いたサンプルデータの場合は、どちらが適切であろうか?

データの性質を考えてみると、全ての変数の値は、
ボランティア活動に費やした「1年当たりの活動従事日数」であった。

つまり、変数間の単位は一定であり、変数間に差はあるものの、
その差の大きさも重要な情報である

したがって、分散共分散行列の方が適しているように思える。

さて、ここまで二回に分けて、主成分分析の仕組みを解説してきたが、
仕組みを理解し、実行したただけでは、まだ、利用できたと言えない。

重要なことは、結果を「読み取る」こと

次回からは、可視化の方法も含めて、結果を読み取る方法について考えることにする。

2012/09/02

文系のための「数の可視化」(8)

分析の基本は、分析の前にデータの性質を理解することである。
分析対象の性質を理解した上で、適切な分析手法を選択する必要がある。

残念ながら有名な分析手法の名前に踊らされる人は多く、
「○○の研究での実績があるから...」とか、「○○先生が使っていたし...」とか、
不可解かつ非論理的な理由で分析する人まで居る。理解できない。

信じ難いのであるが、そんな話が常識となっている分野も存在する。
まぁ、このブログを読んでいる人には、そのような人は居まい。

さて、そのような愚痴はさておき、
本日は多次元データの要約を可視化する方法について考える。

ケトレーの話にも通じるが、データを観察する上で最も基本となるのは、
データの中心からのバラツキであって、
分散標準偏差共分散相関係数といった指標があった。
また、これらの指標に加えて、四分位ヒンジというのもあった。

さらに、それを可視化する方法として、
ヒストグラム散布図箱ヒゲ図、などがあった。

ところで、分散共分散あるいは相関係数を同時に表現する方法として、
分散共分散行列相関係数行列があった。

そこで、今回は分散共分散行列と相関係数行列を可視化する方法について述べる。

分散共分散行列相関係数行列はどのような構造であったか?

確か、分散共分散行列の場合は、対角成分に分散が入っていて、
その他の成分には共分散が入っているような対象行列であった。

一方、相関係数行列は、対角成分が「1」であり、
その他の成分には、相関係数が入っているような対象行列であった。

つまり、結論から述べると散布図行列というのは、
対角成分にバラツキを表すグラフが入り、
それ以外の成分には、散布図が入るような視覚化方法である。

散布図行列には、様々なバリエーションが存在し得るので、
今回は、基本的な見方基本的な形式のみを紹介する。

では、さっそく、データを読み込んでみる。
今回は、いつもとは異なった方法でデータの読み込みを行なってみる

今回のデータは少し大きいので、Google Spreadsheet にデータを置いてある。
このデータを利用するためには、RCurlというパッケージを必要とする。

インストールした記憶の無い人は、まずは、このパッケージをインストールする。
インストールの説明は、新しい箱ヒゲ図の話でしているので、そちらを参照。

install.packages("RCurl", dep=TRUE)

インストールできたら、とりあえず、ライブラリを読み込む

library(RCurl)

ライブラリを無事に読み込めたら、次は、以下のコマンドを実行する。

# Google Spreadsheet からデータをダウンロードする
data <- getURL("https://docs.google.com/spreadsheet/pub?key=0AtOtIs5BjRVhdHo0c0pjb29OTU9aV3BmQUFJUWJQa0E&single=true&gid=0&range=A1%3AK48&output=csv")

# ダウンロードしたデータを読み込む
X <- read.table(textConnection(data), header=TRUE, row.names=1, sep=",")

エラーが出なければ問題は無いはず。念のために、データの確認を行う。

head(X)

head()関数は、データの先頭6行を読み込んで表示するための関数。
データの中身を確認するために用いる。実行結果は以下の通り。

> head(X)
               HM  ELD   HC  CHR   SC   LI   SP  ENV  DIS   IC
Hokkaido     11.3 35.1 34.1 21.2 44.3 14.4 15.5 24.1  5.4 17.9
Aomori-ken   15.2 21.0 22.4 13.3 55.2  7.9  8.4 19.9  8.3  8.0
Iwate-ken     6.0 26.1 12.5 15.9 33.1 10.6 15.6 16.9 11.8 26.9
Miyagi-ken   22.8 40.6 32.8 20.7 43.4 13.4 14.3 22.6 15.2 40.4
Akita-ken     4.9 19.5 25.1 16.1 41.2  7.4  9.8 12.8 10.4 33.2
Yamagata-ken  7.4 26.5 13.4 15.8 33.3  9.5 11.4 13.0  5.9  8.7

このデータは、総務省統計局からダウンロードしたデータを加工したもので、
都道府県別のボランティア活動に従事した人の年平均従事時間(日/年)のデータ。

書く変数の意味は次の通り。
  • HM:健康や医療サービスに関係した活動
  • ELD:高齢者を対象とした活動
  • HC:障害者を対象とした活動
  • CHR:子供を対象とした活動
  • SC:スポーツ・文化・芸術・学術に関係した活動
  • LI:まちづくりのための活動
  • SP:安全な生活のための活動
  • ENV:自然や環境を守るための活動
  • DIS:災害に関係した活動
  • IC:国際強力に関係した活動
当然、全ての人に聞くことはできないので、サンプル調査の結果であり、
男女を合わせた総数での結果となっている。

さて、まずは、分散共分散行列相関係数行列を確認。
小数点が大きすぎるので、小数点第三位までで丸め込む。

# 分散共分散行列
round(cov(X), 3)

# 相関係数行列
round(cor(X), 3)

実行結果は以下の通り。

> # 分散共分散行列
> round(cov(X), 3)
         HM    ELD      HC    CHR     SC     LI     SP    ENV    DIS      IC
HM   27.370  0.750   5.470 -2.063  7.600  2.305 -5.029  5.586 -1.925 -12.463
ELD   0.750 38.669  22.176 10.859 -2.048  9.253  4.594 16.180 -0.199  44.576
HC    5.470 22.176 103.638 11.745  6.029  9.985  3.673 12.545 -0.205  64.775
CHR  -2.063 10.859  11.745 13.820 -0.021  7.465  8.619 12.185  0.559  11.328
SC    7.600 -2.048   6.029 -0.021 52.300 -2.108  0.040  1.468  1.434   7.519
LI    2.305  9.253   9.985  7.465 -2.108 12.677  5.382 20.473  0.950   0.394
SP   -5.029  4.594   3.673  8.619  0.040  5.382 21.932 12.175  1.550  13.332
ENV   5.586 16.180  12.545 12.185  1.468 20.473 12.175 58.090  0.927  -2.488
DIS  -1.925 -0.199  -0.205  0.559  1.434  0.950  1.550  0.927  7.540  12.452
IC  -12.463 44.576  64.775 11.328  7.519  0.394 13.332 -2.488 12.452 279.265
> # 相関係数行列
> round(cor(X), 3)
        HM    ELD     HC    CHR     SC     LI     SP    ENV    DIS     IC
HM   1.000  0.023  0.103 -0.106  0.201  0.124 -0.205  0.140 -0.134 -0.143
ELD  0.023  1.000  0.350  0.470 -0.046  0.418  0.158  0.341 -0.012  0.429
HC   0.103  0.350  1.000  0.310  0.082  0.275  0.077  0.162 -0.007  0.381
CHR -0.106  0.470  0.310  1.000 -0.001  0.564  0.495  0.430  0.055  0.182
SC   0.201 -0.046  0.082 -0.001  1.000 -0.082  0.001  0.027  0.072  0.062
LI   0.124  0.418  0.275  0.564 -0.082  1.000  0.323  0.754  0.097  0.007
SP  -0.205  0.158  0.077  0.495  0.001  0.323  1.000  0.341  0.121  0.170
ENV  0.140  0.341  0.162  0.430  0.027  0.754  0.341  1.000  0.044 -0.020
DIS -0.134 -0.012 -0.007  0.055  0.072  0.097  0.121  0.044  1.000  0.271
IC  -0.143  0.429  0.381  0.182  0.062  0.007  0.170 -0.020  0.271  1.000

さて、この値のどの部分を注意して観察するべきであったか?
確か、相関係数行列の「1」に近いものと「-1」に近いものに注意するべきであった。
この中では、「0.754」が最も高い。マイナス方向では、最も低いのが「-0.205」である。

では、正負の相関の有無の断定となると色々と手続きが必要であるが、
自然や環境を守るための活動(ENV)」と「まちづくりのための活動(LI)」は、
関係しているように思える。逆に、強い負の関係というのは無さそう。

ふむ。この状況、一つ一つを丁寧に見れば、解らなくは無いのだが、どうも見難い。
そこで、この状況を散布図行列を使って可視化してみる。
pairs(X)

pairs()関数は、散布図行列を作成するための関数であり、
分散共分散行列あるいは相関係数行列の状況を可視化したようなもの。

したがって、相関係数行列の各成分に相当する散布図が、
散布図行列の各要素に相当する散布図になっている。

また、散布図行列の対角を挟んで上側下側散布図は、
x軸とy軸が入れ替わっているだけで、結局は同じ状況を示している。
ここでは、とりあえず、下側にだけ注目してみることにする

まずは、先程の比較的関係が強そうなENVとLIの関係に着目してみる。

ENVと他の変数との相関係数がどこに入っていたかと言うと、
相関係数行列では8行目に入っていた。LIとの関係は、6列目

したがって、散布図行列においても8行目を見てみる。
すると、y軸の目盛りが右側に書いてある。これが、ENVの値

LIとの関係は、相関係数行列における6列目であったので、
そのまま、右方向に進み、6番目の散布図を見てみる。これが、ENVとLIの散布図。
LIの値はというと、6列目に並んでいる散布図の一番上の散布図のx軸に書いてある。

y軸の目盛りは左右交互に、x軸の目盛りは上下交互に書いてあるが、
この見方は、相関係数行列と対比しながら見れば解るであろう。

さて、この8行目の6列目の散布図を見てみると、
他の散布図と比較すると、対角線上に綺麗に点が並んでいるように見える。

LIの値が右側に増えるに従って、ENVの値は上に向かって増加しているので、
この二つの変数は連動している

散布図行列だけを見てみると、LI:CHRSP:CHRも、なんとなく右肩上がり。
この散布図の場所は、それぞれ、6行目4列目7行目4列目なので、
そこに該当する相関係数を見てみると、それぞれ、「0.564」と「0.495」となっていて、
今回のデータで見てみると、相対的に相関係数は高い値となっている。

では、逆に対角線に集まって「なさそうな」ものはどれか?
対角を挟んで下側だけで考えてみる。

SC:CHR(5行目4列目)と、SP:SC(7行目5列目)が、対角線上には並んでいなさそう。
相関係数は、それぞれ、「-0.001」と「0.001」であり、やはり、関連は無さそうである。

この二つは、特に関係してい「なさそうな」組み合わせであるが、
散布図が全体的に散らばっているならば、
散布図に対応する相関係数は±1」よりも「0」に近いハズ。

地域に関する活動は、環境や自然に関わる活動や子供に関する活動と関係していて、
さらに、子供に関する活動と安全な生活に関わる活動が関係している。
直感的に、地域住民の意識として、住環境と子供の安全が重要であるのは納得できる。

逆に、スポーツ・文化・芸術・学術に関係した活動は、健康に関わりそうな話であって、
子供に関する活動や安全な生活に関わる活動とは関係しない、というのも頷ける。

なるほど。直感的に納得できそうな結果である。

さて、散布図行列相関係数行列を可視化したようなものであり、
データの全体を俯瞰する上で、非常に強力なツールではあるが、注意すべき点がある

相関係数行列の場合は、変数が多いと値を見落とす危険性があり、
散布図行列の場合は、目の錯覚で、間違った解釈をする場合がある。

この二つの結果を相互に見比べることが重要!!

今度は、散布図行列をもう少し見やすく整えてみる。
散布図行列には、様々な描き方が存在しているが、
ここでは、psych というパッケージを用いた方法を紹介する。

とりあえず、パッケージのインストールし、ライブラリを読み込む。
既に、インストール済みの場合は、ライブラリの読み込みのみ。

install.packages("psych", dep=TRUE)
library(psych)

psych散布図行列のメソッドは、pairs.panels()関数を用いる。
pairs.panels(X)

psych散布図行列を用いると、対角線にはヒストグラムが配置され、
下側には散布図、上側には相関係数が配置される。

それにしても、色々と煩雑なものが入っていて見難い。
それぞれに意味はあるのだが、必要なもの「のみ」を表示することも重要。
pairs.panels(X, smooth=FALSE, density=FALSE, ellipses=FALSE, scale=TRUE)

パラメータに関しては以下の通り。

  • smooth: 平滑線の描画の有無(今回は表示しない)
  • density: ヒストグラムにカーネルを重ねるかの有無(今回は重ねない)
  • ellipses: 散布図に相関を円で表したものを表示するか否か(今回は表示しない)
  • scale: 上側の相関係数の表示の大きさを相関の強さで変えるか(今回は変える)
このように表示すると、分散共分散行列相関係数行列を見事に可視化できる。
分散に相当するヒストグラムが対角線上に配され、上側には相関係数行列もある。

最初の方法では、相関係数行列散布図行列を見比べる必要があったが、
この方法を用いることで、必要な情報を一目で確認することができる。

今回は、対角線上にヒストグラムを配したが、対角成分に箱ヒゲ図を配する方法もある。
本ブログでは、使用を避けているが、Rコマンダーと呼ばれる、
Rのグラフィカルインタフェースを導入すると、散布図行列の対角は箱ヒゲ図になる。

また、Rの初期状態で利用可能なpairs()関数を拡張することもでき、
その方法は、pairs()関数のヘルプの例に記載されている。
余力のある人は、試してみると良い。それほど、難しくはない。

ところで、相関係数行列を可視化する方法は、散布図行列だけではない。
参考までに、相関プロットも紹介する。


cor.plot(cor(X))



cor.plot()関数を用いると、相関係数行列色分けで表示することができる。
この図において、白色のセルは相関係数が低く、青色のセルは値が高い。
逆に、赤色のセルは赤色で表示されている。

変数の数が多くなると、どうしても、相関係数行列散布図行列が見難くなる。
そのような場合には、この方法で可視化して全体を把握することもできる。

2012/09/01

文系のための「多次元データの要約」(1)

今回は、分散と共分散を楽して「行列」を使って計算するという話。

まずは、復習から。分散の計算は、以下の式で表すことができた。
本来は、二乗の形で表すが、共分散の式との比較のため、このように表す。



一方、共分散の計算は、以下のように表した。
共分散の場合は、二つの変数間のバラツキを表すので、
 と  の二つの変数が使われている。



さて、ここからが今回の話の重要なポイント。
今回は、ちょっとした、行列の掛け算の魔法を垣間見ることになる。

まずは、 」分散の計算から考えてみる。
以下は、 」偏差であり、 」という記号で表した。
「〜」の記号は、チルダと呼ぶのだった。



ここで、 というベクトルの計算を考えてみる。これを展開するとどのようになるか?
tの記号は、転置(transpose)を意味したのだから、


このようになる。これは、どのような計算だったか?
忘れた人は、文系のための内積(1)を参照。

確か、「横✕縦+横✕縦+横✕縦・・・となるから・・・。」

おぉ、なるほど。二乗したのを足していく訳か。
あるベクトルの転置と元のベクトルの掛け算は「二乗和」になるのだった。

したがって、以下のようになる。



うん?これは、確か分散の式のΣの内側と同じ計算となっている。
何が言いたいかと言うと、分散の計算をベクトルで表すと、以下のようになる。



 の分散は、見事にベクトルの式で表すことができる。
確か、共分散のΣの中身は、添字が異なるだけで、分散と同じだった。
つまり、掛ける側のベクトルを とすると、



となり、したがって、



という計算になる。素晴らしい。分散と同様に見事に計算できる
分散と同様に、ベクトルの式で表すと、次のようになる。



ここまでが理解できれば大丈夫。ここまでは、ベクトルの掛け算であったが、
次のような行列を考えてみるとどうなるか?



ちょっと、難しいかもしれないが、落ち着いて考えれば大丈夫。
頑張れる人は、手計算で。自信が無い人は、行列の計算の話を参考に。
頑張れない人は、あとでRを使って練習。

計算の順番と解となる行列での位置は次のようになる。
  • 1行目の横ベクトル×1列目の縦ベクトル(  ) ⇒  Answer[1, 1]
  • 1行目の横ベクトル×2列目の縦ベクトル(  ) ⇒  Answer[1, 2]
  • 1行目の横ベクトル×3列目の縦ベクトル(  ) ⇒  Answer[1, 3]
  • 2行目の横ベクトル×1列目の縦ベクトル(  ) ⇒  Answer[2, 1]
  • 2行目の横ベクトル×2列目の縦ベクトル(  ) ⇒  Answer[2, 2]
  • 2行目の横ベクトル×3列目の縦ベクトル(  ) ⇒  Answer[2, 3]
  • 3行目の横ベクトル×1列目の縦ベクトル(  ) ⇒  Answer[3, 1]
  • 3行目の横ベクトル×2列目の縦ベクトル(  ) ⇒  Answer[3, 2]
  • 3行目の横ベクトル×3列目の縦ベクトル(  ) ⇒  Answer[3, 3]
つまり、以下のように書き換えることが可能。



ここで、注意して見てもらいたいのが、対角成分に何が入っているか?ということ。
自分同士の共分散ということは、何を意味するのだったか?答えは、分散

もうひとつのポイントは、二つの変数の共分散の計算は、
順番を変えても答えは同じ(スカラーでは、A×B=B×A)なので、
対角成分を挟んで上側と下側が同じになる、ということも重要。

したがって、この行列の計算を通して計算された結果は、
対角成分に分散が並び、それ以外に共分散が入った対象行列である。

これを、「分散共分散行列」と呼ぶ。

さらに、元の行列が標準化されていた場合、すなわち、
平均が「0」で分散が「1」となるように基準化されていた場合には、
対角成分が全て「1」で、それ以外の成分が相関係数となる

例えば、先ほどの行列 を標準化した行列を Z としたとき、



という関係が成り立つ。これを、「相関係数行列」と呼ぶ。

分散共分散行列相関係数行列は、データを要約した指標として重要であると同時に、
この行列を用いることで、主成分分析の計算が容易になる。この話は、いずれ。

では、今度は実際のデータを用いて計算の練習をしてみる。
サンプルデータは、分散標準偏差の説明で用いたものを再び使う。

# Windows と Linux の人は次のコマンド
X <- read.table("clipboard", sep=",", header=TRUE)

# Mac の人は次のコマンド
X <- read.table(pipe("pbpaste") , sep=",", header=TRUE)

以下が、そのデータ。前回のものを再掲しただけ。
データの説明に関しては、平均の話を参照。

Oroshi_Kg, Taka, Naka, Yasu
Tai, 1336, 3150, 1217, 53
Chinu, 226, 630, 513, 105
Sawara, 212, 1575, 1259, 840
Yazu, 4834, 840, 315, 179
Suzuki, 618, 1575, 1146, 525
Akou, 21, 4725, 3129, 1575
Kochi, 28, 2100, 874, 210
Okoze, 28, 5250, 2635, 210
Ainame, 29, 3150, 621, 315
Hage, 1205, 1890, 383, 210
Konoshiro, 21, 2100, 1100, 105
Sayori, 12, 5250, 3916, 1260
Anago, 1637, 2625, 1721, 630
Mebaru, 330, 4200, 1680, 315
Tachiuo, 1211, 2310, 930, 105
Hamo, 1622, 3938, 592, 53
Karei, 41, 6300, 3178, 525
Hirame, 540, 2100, 1496, 210
Aji, 5149, 3150, 789, 210
Saba, 5413, 3675, 625, 53
Ika, 2414, 2888, 1083, 105
Tako, 1844, 1890, 1180, 525
Ebi, 560, 7350, 1420, 525
KurumaEbi, 222, 8925, 6508, 2625
Koiwashi, 1316, 1155, 617, 328
ObaIwashi, 2716, 499, 267, 175
Mentai, 678, 1155, 859, 394
Hamachi, 4772, 998, 632, 105
Isaki, 268, 2625, 1465, 840

まずは、行列 と同じサイズで、平均が並んでいる行列が必要だから、

# ステップ1:データの総数(n)を求める。
n <- nrow(X)
# ステップ2:卸売数量の平均を求める。転置が必要。
m <- t(colMeans(X))
# ステップ3:行列の引き算ができるように、平均値を総数個複製する。
M <- matrix(rep(m, each=n), nrow=n, ncol=4)
# ステップ4:元の行列から、平均値が複製された行列Mを引き算する。
tilde_X <- as.matrix(X-M)

最終的に、「tilde_X」という変数に偏差行列が入った。
ここで、分散共分散の式をそのまま当てはめると、

(t(tilde_X) %*% tilde_X)/(n-1)

となり、実行結果は以下のようになる。

> (t(tilde_X) %*% tilde_X)/(n-1)
           Oroshi_Kg       Taka      Naka      Yasu
Oroshi_Kg  2814792.6 -1026368.1 -920404.3 -335784.2
Taka      -1026368.1  4210888.7 2159783.0  685439.7
Naka       -920404.3  2159783.0 1752709.8  637497.8
Yasu       -335784.2   685439.7  637497.8  306021.7

疑い深い人は、分散共分散の話の結果と照合してみよう。
間違いなく、対角成分には分散が並び、それ以外には共分散が入っている。

さて、今度は、元のデータを標準化して計算をしてみる。

# 標準化した行列を作る
Z <- scale(X)

# 共分散の計算。平均は0なので偏差行列は不要
(t(Z) %*% Z)/(n-1)

実行結果は以下の通り。

> cov(Z)
           Oroshi_Kg       Taka       Naka       Yasu
Oroshi_Kg  1.0000000 -0.2981213 -0.4143816 -0.3617937
Taka      -0.2981213  1.0000000  0.7950020  0.6038183
Naka      -0.4143816  0.7950020  1.0000000  0.8704575
Yasu      -0.3617937  0.6038183  0.8704575  1.0000000

対角成分には「1」が並んでいて、それ以外の所は相関係数が入っている。
このようにして、相関係数行列を計算することができる。

ちなみに、前回、登場したcov()関数cor()関数は、
両方とも行列に対応しているので、共分散行列相関係数行列を出せる。

cov(X)    # 分散共分散行列を直接計算する
cor(X)    # 相関係数行列を直接計算する

以下は、実行結果。

> cov(X)    # 分散共分散行列を直接計算する
           Oroshi_Kg       Taka      Naka      Yasu
Oroshi_Kg  2814792.6 -1026368.1 -920404.3 -335784.2
Taka      -1026368.1  4210888.7 2159783.0  685439.7
Naka       -920404.3  2159783.0 1752709.8  637497.8
Yasu       -335784.2   685439.7  637497.8  306021.7

> cor(X)    # 相関係数行列を直接計算する
           Oroshi_Kg       Taka       Naka       Yasu
Oroshi_Kg  1.0000000 -0.2981213 -0.4143816 -0.3617937
Taka      -0.2981213  1.0000000  0.7950020  0.6038183
Naka      -0.4143816  0.7950020  1.0000000  0.8704575
Yasu      -0.3617937  0.6038183  0.8704575  1.0000000

手計算の場合には、結局、展開して計算しないといけないので、
手間は同じであるが、Rのように行列の計算ができるソフトウェアを使えば、
分散共分散相関係数を一度に計算することができ、便利なのである。