目的 主成分分析を行う。 R には,princomp および prcomp という,二種類の関数が用意されている。 しかし,これらが返す「loadings」は固有ベクトルそのものであって,いわゆる負荷量ではない。 そこで,princomp2,prcomp2 という関数を書いたので,そちらも参照してみるとよい。 使用法 pca(dat) print.pca(obj, npca=NULL, digits=3) summary.pca(obj, digits=5) plot.pca(obj, which=c("loadings", "scores"), pc.no=c(1,2), ax=TRUE, label.cex=0.6, ...) 引数 dat データフレームまたはデータ行列(行がケース,列が変数) obj pca が返すオブジェクト npca 表示する主成分数 digits 結果の表示桁数 which 主成分負荷量か主成分得点か pc.no 描画する主成分番号 ax 座標軸を描き込むかどうか label.cex 主成分負荷量のプロットのラベルのフォントサイズ ... plot に引き渡す引数 ソース インストールは,以下の 1 行をコピーし,R コンソールにペーストする source("http://aoki2.si.gunma-u.ac.jp/R/src/pca.R", encoding="euc-jp") # 主成分分析 pca <- function(dat) # データ行列 { if (is.null(rownames(dat))) rownames(dat) <- paste("#", 1:nrow(dat), sep="") dat <- subset(dat, complete.cases(dat)) # 欠損値を持つケースを除く nr <- nrow(dat) # サンプルサイズ nc <- ncol(dat) # 変数の個数 if (is.null(colnames(dat))) { colnames(dat) <- paste("X", 1:nc, sep="") } vname <- colnames(dat) heikin <- colMeans(dat) # 各変数の平均値 bunsan <- apply(dat, 2, var) # 各変数の不偏分散 sd <- sqrt(bunsan) # 各変数の標準偏差 r <-cor(dat) # 相関係数行列 result <- eigen(r) # 固有値・固有ベクトルを求める eval <- result$values # 固有値 evec <- result$vectors # 固有ベクトル contr <- eval/nc*100 # 寄与率(%) cum.contr <- cumsum(contr) # 累積寄与率(%) fl <- t(sqrt(eval)*t(evec)) # 主成分負荷量 fs <- scale(dat)%*%evec*sqrt(nr/(nr-1)) # 主成分得点 names(heikin) <- names(bunsan) <- names(sd) <- rownames(r) <- colnames(r) <- rownames(fl) <- colnames(dat) names(eval) <- names(contr) <- names(cum.contr) <- colnames(fl) <- colnames(fs) <- paste("PC", 1:nc, sep="") return(structure(list(mean=heikin, variance=bunsan, standard.deviation=sd, r=r, factor.loadings=fl, eval=eval, contribution=contr, cum.contribution=cum.contr, fs=fs), class="pca")) } # print メソッド print.pca <- function( obj, # pca が返すオブジェクト npca=NULL, # 表示する主成分数 digits=3) # 結果の表示桁数 { eval <- obj$eval nv <- length(eval) if (is.null(npca)) { npca <- sum(eval >= 1) } eval <- eval[1:npca] cont <- eval/nv cumc <- cumsum(cont) fl <- obj$factor.loadings[, 1:npca, drop=FALSE] rcum <- rowSums(fl^2) vname <- rownames(fl) max.char <- max(nchar(vname), 12) fmt1 <- sprintf("%%%is", max.char) fmt2 <- sprintf("%%%is", digits+5) fmt3 <- sprintf("%%%i.%if", digits+5, digits) cat("\n主成分分析の結果\n\n") cat(sprintf(fmt1, ""), sprintf(fmt2, c(sprintf("PC%i", 1:npca), " Contribution")), "\n", sep="", collapse="") for (i in 1:nv) { cat(sprintf(fmt1, vname[i]), sprintf(fmt3, c(fl[i, 1:npca], rcum[i])), "\n", sep="", collapse="") } cat(sprintf(fmt1, "Eigenvalue"), sprintf(fmt3, eval[1:npca]), "\n", sep="", collapse="") cat(sprintf(fmt1, "Contribution"), sprintf(fmt3, cont[1:npca]), "\n", sep="", collapse="") cat(sprintf(fmt1, "Cum.contrib."), sprintf(fmt3, cumc[1:npca]), "\n", sep="", collapse="") } # summary メソッド summary.pca <- function(obj, # pca が返すオブジェクト digits=5) # 結果の表示桁数 { print.default(obj, digits=digits) } # plot メソッド plot.pca <- function( obj, # pca が返すオブジェクト which=c("loadings", "scores"), # 主成分負荷量か主成分得点か pc.no=c(1,2), # 描画する主成分番号 ax=TRUE, # 座標軸を描き込むかどうか label.cex=0.6, # 主成分負荷量のプロットのラベルのフォントサイズ ...) # plot に引き渡す引数 { which <- match.arg(which) if (which == "loadings") { d <- obj$factor.loadings } else { d <- obj$fs } label <- sprintf("第%i主成分", pc.no) plot(d[, pc.no[1]], d[, pc.no[2]], xlab=label[1], ylab=label[2], ...) if (which == "loadings") { text(d[, pc.no[1]], d[, pc.no[2]], rownames(obj$factor.loadings), pos=1, cex=label.cex) } abline(h=0, v=0) } 使用例 > set.seed(123) > x <- matrix(rnorm(1000), 100) > colnames(x) <- paste("X", 1:10, sep="") > a <- pca(x) > print(a) # print メソッドによる出力 主成分分析の結果 PC1 PC2 PC3 PC4 PC5 Contribution X1 0.517 0.477 -0.052 0.047 -0.187 0.535 X2 -0.068 -0.010 -0.443 -0.643 0.328 0.722 X3 -0.306 -0.251 -0.289 0.069 0.467 0.462 X4 0.513 -0.579 0.179 -0.186 0.168 0.694 X5 -0.502 -0.309 0.474 -0.063 -0.432 0.763 X6 -0.337 0.125 0.410 -0.669 0.004 0.744 X7 -0.037 -0.158 -0.525 -0.125 -0.529 0.598 X8 0.557 0.214 0.200 -0.424 -0.107 0.587 X9 -0.181 0.520 0.330 0.150 0.382 0.580 X10 0.371 -0.461 0.327 0.136 0.186 0.510 Eigenvalue 1.477 1.290 1.239 1.143 1.047 Contribution 0.148 0.129 0.124 0.114 0.105 Cum.contrib. 0.148 0.277 0.401 0.515 0.620 > plot(a) # plot メソッドにより,以下のような図を描くことができる > summary(a) # summary メソッドは,すべての結果を表示する $mean # 平均値 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 0.090406 -0.107547 0.120465 -0.036223 0.105851 -0.042300 -0.149644 0.105874 0.093590 -0.019193 $variance # 分散 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 0.83323 0.93506 0.90227 1.07907 0.97881 0.88121 1.05727 1.02012 1.10630 1.04108 $standard.deviation # 標準偏差 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 0.91282 0.96699 0.94988 1.03878 0.98935 0.93873 1.02824 1.01001 1.05181 1.02033 $r # 相関係数行列 X1 X2 X3 X4 X5 X6 X7 X8 X9 X1 1.000000 -0.049532 -0.1291760 -0.044079 -0.1927111 -0.056484 -0.03436677 0.18157297 -0.022603 X2 -0.049532 1.000000 0.0305790 0.043833 -0.1306222 0.114488 0.07811288 -0.03312350 -0.045328 X3 -0.129176 0.030579 1.0000000 -0.044866 -0.0248484 0.018210 0.00868518 -0.11502946 -0.053282 X4 -0.044079 0.043833 -0.0448657 1.000000 -0.0192599 -0.089913 -0.06378733 0.16789328 -0.165068 X5 -0.192711 -0.130622 -0.0248484 -0.019260 1.0000000 0.206618 -0.00650252 -0.14065351 -0.039583 X6 -0.056484 0.114488 0.0182101 -0.089913 0.2066177 1.000000 -0.06469260 0.09415014 0.074363 X7 -0.034367 0.078113 0.0086852 -0.063787 -0.0065025 -0.064693 1.00000000 0.00026531 -0.128910 X8 0.181573 -0.033123 -0.1150295 0.167893 -0.1406535 0.094150 0.00026531 1.00000000 -0.000812 X9 -0.022603 -0.045328 -0.0532819 -0.165068 -0.0395835 0.074363 -0.12891005 -0.00081201 1.000000 X10 0.011005 -0.091490 -0.0144420 0.245212 -0.0160433 -0.025055 -0.02046957 0.02425240 -0.022721 X10 X1 0.011005 X2 -0.091490 X3 -0.014442 X4 0.245212 X5 -0.016043 X6 -0.025055 X7 -0.020470 X8 0.024252 X9 -0.022721 X10 1.000000 $factor.loadings # 主成分負荷量 PC1 PC2 PC3 PC4 PC5 PC6 PC7 PC8 PC9 X1 0.517278 0.476861 -0.052369 0.046502 -0.1869609 0.285421 -0.077013 0.489319 0.368549 X2 -0.068118 -0.010183 -0.443158 -0.642999 0.3283064 -0.345063 -0.136811 0.220083 0.141827 X3 -0.305558 -0.251422 -0.288849 0.068673 0.4666195 0.664353 0.214749 -0.061908 0.209696 X4 0.513138 -0.579260 0.178953 -0.186259 0.1683695 -0.116629 -0.173785 -0.209851 0.331968 X5 -0.502346 -0.308797 0.473858 -0.063168 -0.4317162 0.033310 -0.114150 0.041986 0.371840 X6 -0.336515 0.124599 0.409766 -0.668959 0.0036195 0.206013 0.166547 0.221193 -0.161331 X7 -0.036841 -0.158350 -0.525102 -0.125233 -0.5292793 -0.137064 0.581665 -0.073112 0.141855 X8 0.557055 0.213936 0.200370 -0.423696 -0.1074629 0.266109 0.181577 -0.454372 -0.060737 X9 -0.181014 0.519696 0.330143 0.149726 0.3820022 -0.351764 0.390861 -0.180442 0.330547 X10 0.371304 -0.460744 0.327348 0.135656 0.1861430 -0.105584 0.471437 0.441483 -0.150436 PC10 X1 -0.050095 X2 0.267016 X3 0.047445 X4 -0.328692 X5 0.288470 X6 -0.332676 X7 -0.139382 X8 0.314292 X9 -0.038484 X10 0.196728 $eval # 固有値 PC1 PC2 PC3 PC4 PC5 PC6 PC7 PC8 PC9 PC10 1.47679 1.29035 1.23907 1.14254 1.04747 0.92354 0.88806 0.82569 0.63012 0.53637 $contribution # 主成分距率 PC1 PC2 PC3 PC4 PC5 PC6 PC7 PC8 PC9 PC10 14.7679 12.9035 12.3907 11.4254 10.4747 9.2354 8.8806 8.2569 6.3012 5.3637 $cum.contribution # 累積寄与率 PC1 PC2 PC3 PC4 PC5 PC6 PC7 PC8 PC9 PC10 14.768 27.671 40.062 51.487 61.962 71.198 80.078 88.335 94.636 100.000 $fs # 主成分得点 PC1 PC2 PC3 PC4 PC5 PC6 PC7 PC8 #1 -1.612555 -0.273815 -1.6185782 1.08688059 0.2832542 1.092703 0.8801606 -0.89722227 #2 -0.843994 -0.182274 -2.2869553 1.11084435 0.8932829 0.327667 -0.5543246 0.25070182 #3 0.043907 1.585518 0.1595640 0.05497306 0.0034773 0.038015 0.6262311 1.70524691 #4 -0.306952 0.515026 1.4935579 0.32611764 1.3911034 0.333032 0.9030307 1.01841905 #5 -0.148867 -0.744177 -0.2274698 2.14464144 -0.9172497 -1.052776 0.6208851 0.73431644 中略 #99 -0.6323143 -0.332812 #100 -0.9801591 -0.419919 attr(,"class") [1] "pca" > b <- pca(iris[1:4]) > plot(b, which="scores", col=c("black", "red", "blue")[as.integer(iris[,5])], + pch=c(19, 1, 2)[as.integer(iris[,5])]) # 主成分得点の描画 (正準判別分析の結果と比較してみよ) 解説ページ