R/bassAckward.R

Defines functions summary_psych.back print_psych.back

"bassAckward" <- function(r,nfactors=1,fm="minres",rotate="oblimin",scores="tenBerge",adjust=TRUE,plot=TRUE,cut=.3,use="pairwise", cor="cor",weight=NULL,correct=.5,...) {
 cl <- match.call()
#find r if data matrix
    if (!isCorrelation(r)) {  matrix.input <- FALSE  #return the correlation matrix in this case
                       n.obs <- dim(r)[1]
                       cnames <- colnames(r)
   
    # if given a rectangular matrix, then find the correlation or covariance 
    #multiple ways of find correlations or covariances
    #added the weights option to tet, poly, tetrachoric, and polychoric  June 27, 2018
    switch(cor, 
       cor = {r <- cor(r,use=use)},
       cov = {r <- cov(r,use=use) 
              covar <- TRUE},
       wtd = { r <- cor.wt(r,w=weight)$r},
       tet = {r <- tetrachoric(r,correct=correct,weight=weight)$rho},
       poly = {r <- polychoric(r,correct=correct,weight=weight)$rho},
       tetrachoric = {r <- tetrachoric(r,correct=correct,weight=weight)$rho},
       polychoric = {r <- polychoric(r,correct=correct,weight=weight)$rho},
       mixed = {r <- mixedCor(r,use=use,correct=correct)$rho},
       Yuleb = {r <- YuleCor(r,,bonett=TRUE)$rho},
       YuleQ = {r <- YuleCor(r,1)$rho},
       YuleY = {r <- YuleCor(r,.5)$rho } 
       )
      colnames(r) <- rownames(r) <- cnames 
  }

r.n <- list()
fa <- list()
Phi <- list()
fa.Vaccounted <- list()
num.fac <- length(nfactors)
if (num.fac == 1L) { num.fac <- nfactors 
        nfactors <- 1:num.fac}
  
if(fm =="pca") {
#do the conventional pca bass-akwards approach with components
pc <- pca(r,nfactors[1],rotate=rotate)
#pc <- pca(r)
pc.weights <- pc$weights
colnames(pc.weights) <- paste0("C",1:nfactors[1])
for(nf in 1:num.fac) {
fn <- pca(r,nfactors[nf],rotate=rotate)
colnames(fn$loadings) <-    paste0("C",1:ncol(fn$loadings))
fa[[nf]] <- fn$loadings
Phi[[nf]] <- fn$Phi
fa.Vaccounted[[nf]] <- fn$Vaccounted[2,]
pcn.weights <- fn$weights
colnames(pcn.weights) <- paste0("C",1:ncol(pcn.weights))
colnames(pc$weights) <- paste0("C",1:ncol(pc$weights))
r.n[[nf]] <-  t(pcn.weights) %*% r %*% pc$weights  
pc <- fn
}
} else { #factor analyze
#two cases:
#normal case is do a regular factor analysis
#but, if rotate = "schmid" we do a schmid leiman rotation 
if(rotate != "schmid") {
f <- fa(r,nfactors[1],fm=fm,rotate=rotate,scores=scores) 
for(nf in 1:num.fac) {
fn <- fa(r,nfactors[nf],fm=fm,rotate=rotate,scores=scores)
colnames(fn$loadings) <-  paste0("F",1:ncol(fn$loadings))
fa[[nf]] <- fn$loadings
Phi[[nf]] <- fn$Phi
fn.weights <- fn$weights
fa.Vaccounted[[nf]] <- fn$Vaccounted[2,]
colnames(fn.weights) <- paste0("F",1:ncol(fn$weights))
colnames(f$weights) <- paste0("F",1:ncol(f$weights))



rf  <-  t(fn.weights) %*% r %*% f$weights  #need to adjust by  variances if not using tenBerge
rs1 <- diag(t(f$weights) %*% r %*% f$weights )
rs2 <- diag(t(fn$weights) %*% r %*% fn$weights )
if(adjust) rf <- (diag(1/sqrt(rs2)) %*% rf %*% diag(1/sqrt(rs1)))
colnames(rf) <- paste0("F",1:ncol(rf))
rownames(rf) <- paste0("F",1:nrow(rf))
r.n[[nf]] <- rf
f <- fn}

}  else {  #do schmid leiman extractions

f <- schmid(r,nfactors[1],fm=fm)    #the top level

f$weights <- solve(r,f$sl[,1:(nfactors[1]+1)]) 
for(nf in 1:num.fac) {
fn <- schmid(r,nfactors[nf],fm=fm)
fn$loadings <- fn$sl[,1:(nfactors[nf] + 1)]
colnames(fn$loadings) <- c("g", paste0("F*",1:(ncol(fn$loadings)-1)))
fa[[nf]] <- fn$loadings
fn$weights <- solve(r,fn$loadings)
colnames(fn$weights) <- c("g",paste0("F*",1:(ncol(fn$weights)-1)))
colnames(f$weights) <- c("g", paste0("F*",1:(ncol(f$weights)-1)))
Phi <- NULL
rf  <-  t(fn$weights) %*% r %*% f$weights  #need to adjust by  variances if not using tenBerge
rs1 <- diag(t(f$weights) %*% r %*% f$weights )
rs2 <- diag(t(fn$weights) %*% r %*% fn$weights )
if(adjust) rf <- (diag(1/sqrt(rs2)) %*% rf %*% diag(1/sqrt(rs1)))
colnames(rf) <- c("g",paste0("F*",1:(ncol(rf)-1)))
rownames(rf) <- c("g", paste0("F*",1:(nrow(rf)-1)))
r.n[[nf]] <- rf
f <- fn
}
}
}

#Now summarize the results 
sumlist <-  sumnames <- labels <-  list()
fa.loading.phi <-list()
for(f in 1:nf) {
sumlist[[f]] <- apply(r.n[[f]],2,function(x) {which(max(abs(x))==abs(x))})
sumnames[[f]] <- rownames(r.n[[f]])[sumlist[[f]]]
labels[[f]] <- rownames(r.n[[f]])
if(length(Phi)>0) { #added this check March 3, 2020 
fa.loading.phi [[f]] <-list(loadings = fa[[f]],Phi=Phi[[f]])} else {
fa.loading.phi [[f]] <-list(loadings = fa[[f]],Phi=NA) }
class(fa.loading.phi[[f]]) <- cs(psych,fa)
}
labels[[nf+1]] <- rownames(fn$loadings)
r.n[[nf+1]] <- fn$loadings


result <- list(Call=cl,fm=fm,bass.ack= r.n,Phi=Phi,r = r,summary=sumlist,sumnames=sumnames,labels =labels,fa=fa.loading.phi,
        fa.vac=fa.Vaccounted)
class(result) <- c("psych","bassAck")
if(plot) bassAckward.diagram(result,cut=cut,...)
return(result)
}

print_psych.back<- function(x,digits=2 ,short=TRUE) {

   cat("\nCall: ")
   print(x$Call)
nf <- length(x$bass.ack)-1
for (f in 1:nf) {
cat("\n",f, 
x$sumnames[[f]])}

if(!short) {
for (f in 1:nf) {
cat("\nFactor correlations\n ")
print(round(x$bass.ack[[f]],digits=digits))}
}
}

summary_psych.back <- function(x,digits=2) {
cat("\nCall: ")
   print(x$Call)
nf <- length(x$bass.ack)-1
for (f in 1:nf) {
cat("\nFactor correlations\n ")
print(round(x$bass.ack[[f]],digits=digits))
}
}

Try the psych package in your browser

Any scripts or data that you put into this service are public.

psych documentation built on Sept. 26, 2023, 1:06 a.m.