#added checks for GPArotation even though we are already testing somewhere else #the first function finds the first derivative, the second finds the fit "vgbQ.bimin" <- function(L) { k <- dim(L)[2] L2 <- L^2 N <- matrix(1,k,k) diag(N) <- 0 L2N <- L2 %*% N v <- sum(L2 * L2N) G = 4 * L * L2N return(list(f=v,Gq=G)) } "vgQ.bimin" <- function(L) { L2 <- L[,-1] lvg <- vgbQ.bimin(L2) v <- lvg$f G <- lvg$Gq G <-cbind(G[,1],G) G[,1] <- 0 return(list(f=v,Gq=G)) } #adapted from Jennrich and Bentler 2011 #requires GPArotation "bifactor" <- function(L, Tmat=diag(ncol(L)), normalize=FALSE, eps=1e-5, maxit=1000){ if(requireNamespace('GPArotation')) {GPArotation::GPForth(L, Tmat=Tmat, normalize=normalize, eps=eps, maxit=maxit, method="bimin")} else {stop("Bifactor requires GPArotation")} } #the oblique case #requires GPArotation "biquartimin" <- function(L, Tmat=diag(ncol(L)), normalize=FALSE, eps=1e-5, maxit=1000){ if(requireNamespace('GPArotation')) {GPArotation::GPFoblq(L, Tmat=Tmat, normalize=normalize, eps=eps, maxit=maxit, method="bimin") } else {stop("biquartimin requires GPArotation")} } #this is a minor patch to the target function to allow it to have missing elements in the target so it more closely approximates the Michael Brown function "vgQ.targetQ" <- function (L, Target = NULL) { if (is.null(Target)) stop("argument Target must be specified.") Gq <- 2 * (L - Target) Gq[is.na(Gq)] <- 0 list(Gq = Gq, f = sum((L - Target)^2,na.rm=TRUE), Method = "Target rotation") } #these next two take advantage of the revised vgQ.targetQ to do oblique or orthogonal rotations "TargetQ" <- function(L, Tmat=diag(ncol(L)), normalize=FALSE, eps=1e-5, maxit=1000,Target=NULL) { if(requireNamespace('GPArotation')) {GPArotation::GPFoblq(L, Tmat=Tmat,normalize=normalize, eps=eps, maxit=maxit, method="targetQ",Target)} else {stop("TargetQ requires GPArotation")}} "TargetT" <- function(L, Tmat=diag(ncol(L)), normalize=FALSE, eps=1e-5, maxit=1000,Target=NULL) { if(requireNamespace('GPArotation')) {GPArotation::GPForth(L, Tmat=Tmat,normalize=normalize, eps=eps, maxit=maxit, method="targetQ",Target)} else {stop("TargetT requires GPArotation")}}