# External PCA function ---
# used to check results
PCA <- function(R, k = NULL){
if(is.null(k)) k <- ncol(R)
VLV <- eigen(R)
V <- VLV$vectors
L <- VLV$values
if( k > 1){
P <- V[, 1:k] %*% diag(L[1:k]^.5)
}
else{
P <- as.matrix(V[, 1], drop=False) * L[1]^.5
}
Psign <- sign(apply(P, 2, sum))
if(k > 1) Psign = diag(Psign)
P <- P %*% Psign
P
}#END PCA
## Generate Desired Population rotated PCA loadings matrix
## Example = 1
k = 2
F <- matrix(0, 8, 2)
F[1:4, 1] <- seq(.75, .72, length= 4)
F[5:8, 2] <- seq(.65, .62, length= 4)
F[1,2] <- .1234
F[8,1] <- .4321
colnames(F) <- paste0("F", 1:k)
(F)
## Run Example 1
pout <- rPCA(F,
maxit = 5000,
Seed = 1,
epsMax = 1E-18,
PrintLevel = 1)
pout$converged
eigen(pout$R)$values
if(pout$error == FALSE & pout$converged){
Fhat <- pout$Fhat
cat("\nPCA Loadings\n")
( round( cbind(F,Fhat ), 5) )
}
## Example = 2
## Single component example from Widaman 2018
k = 1
F <- matrix(rep(c(.8,.6, .4), each = 3 ), nrow = 9, ncol = 1)
colnames(F) <- paste0("F", 1:k)
(F)
## Run Example 2
pout <- rPCA(F,
maxit = 5000,
Seed = 1,
epsMax = 1E-18,
PrintLevel = 1)
pout$converged
pout$Fhat
eigen(pout$R)$values
if(pout$error == FALSE & pout$converged){
Fhat <- pout$Fhat
cat("\nPCA Loadings\n")
( round( cbind(F,Fhat ), 5) )
}
## Example 3 ----
## 2 Component example from Goldberg and Velicer (2006).
k = 2
F = matrix(c( .18, .75,
.65, .19,
.12, .69,
.74, .06,
.19, .80,
.80, .14,
-.05, .65,
.71, .02), 8, 2, byrow=TRUE)
colnames(F) <- paste0("F", 1:k)
(F)
## Run Example 3
pout <- rPCA(F,
maxit = 5000,
Seed = 1,
epsMax = 1E-18,
PrintLevel = 1)
pout$converged
eigen(pout$R)$values
if(pout$error == FALSE & pout$converged){
Fhat <- pout$Fhat
cat("\nPCA Loadings\n")
( round( cbind(F,Fhat ), 5) )
#
#
## Example 4
#
SEED = 4321
set.seed(SEED)
k= 3
## Generate eigenvalues for example R matrix
L7 <- eigGen(nDimensions = 7,
nMaj = 3,
PrcntMajor = .85,
threshold = .8)
## Scree Plot
plot(1:7, L7,
type = "b",
ylim = c(0,4),
main = "Scree Plot for R",
ylab = "Eigenvalues",
xlab = "Dimensions")
## Generate R
R <- rGivens(eigs=L7, Seed = SEED)$R
print( R, digits = 4)
#Extract loadings for 3 principal components
F <- PCA(R, k = k)
# rotate loadings with varimax to examine underlying structure
print( round(varimax(F)$loadings[], 3) )
## run rPCA with user-defined eigenvalues
rout <- rPCA(F,
epsMax = 1e-20,
maxit = 25000,
Seed = SEED,
InitP2 = 1,
Eigs = L7,
PrintLevel = 1)
## Compute PCA on generated R
Fhat <- PCA(rout$R, k = 3)
#
## align factors
Fhat <- fungible::faAlign(F, Fhat)$F2
## Compare solutions
print( round( cbind(F, Fhat), 5) )
## Compare Eigenvalues
print( cbind(L7, eigen(rout$R)$values ), digits=8)
#
## Compare R matrices: 8 digit accuracy
print( round(R - rout$R, 8) )
}
Run the code above in your browser using DataLab