当面の問題は、
cump[i]=sum(eigenvalue[1:i])/total
eigenvalue
存在しないものを参照します。eig
代わりにここで使用するつもりだったと思います:
cump[i]=sum(eig[1:i])/total
コメントから、エラーは次のようです。
as.vector(x, mode) : cannot coerce type 'closure' to vector of type 'any'
を指定せずに関数を呼び出すため、これが疑わしい結果になりますscale
。その後、R は関数 (クロージャー) を見つけますが、ステートメントscale
に必要な型に強制することはできません。if()
これを解決する簡単な方法は、次のいずれかを実行することです。
lab3 <- function(cov, scale = FALSE) {
....
また
lab3 <- function(cov) {
if(missing(scale))
scale <- FALSE
....
最初の形式が優先されます。
他にも問題があります。
きっとあなたは欲しい
if(scale)
cov <- cov2cor(cov)
? つまり、すべての変数をゼロ平均単位分散にスケーリングする場合にのみ、相関行列が必要です。
次の 2 行を使用すると、for
ループをより効率的に実行できます。
indp <- eig / total
cump <- cumsum(indp)
ループはまったく必要ありません。最初for
にセットアップする必要もありませindp
んcump
。
eigen()
あなたは2回電話します。一度呼び出して、返されたオブジェクト全体を保存することをお勧めします。必要なビットのサブセット。
これらの問題をすべて解決すると、次の機能が得られます。
lab3 <- function(cov, scale=FALSE){
if (scale)
cov <- cov2cor(cov)
ed <- eigen(cov)
eig <- ed$values
total <- sum(eig)
stdev <- sqrt(eig)
rotation <-ed$vectors
indp <- eig / total
cump <- cumsum(eig)
list(stdev, rotation, indp, cump)
}
どちらが機能しますか:
> lab3(cov(iris[, 1:4]))
[[1]]
[1] 2.0562689 0.4926162 0.2796596 0.1543862
[[2]]
[,1] [,2] [,3] [,4]
[1,] 0.36138659 -0.65658877 -0.58202985 0.3154872
[2,] -0.08452251 -0.73016143 0.59791083 -0.3197231
[3,] 0.85667061 0.17337266 0.07623608 -0.4798390
[4,] 0.35828920 0.07548102 0.54583143 0.7536574
[[3]]
[1] 0.924618723 0.053066483 0.017102610 0.005212184
[[4]]
[1] 4.228242 4.470912 4.549122 4.572957
最後に、数値安定性の理由から、固有値分解よりも特異値分解による PCA の方が優れていると考えられることに注意してください。そして、これらすべてをベース R で、princomp
またはできれば経由で行うことができます。prcomp