@@ -322,8 +322,12 @@ confirmatoryFactorAnalysisInternal <- function(jaspResults, dataset, options, ..
322322 if (options [[" dataType" ]] == " varianceCovariance" ) {
323323 .quitAnalysis(gettext(" Bootstrapping is not available for variance-covariance matrix input." ))
324324 }
325- cfaResult [[" lav" ]] <- jaspSem :: lavBootstrap(cfaResult [[" lav" ]], options $ bootstrapSamples ,
326- standard = options [[" standardized" ]] != " none" , typeStd = type )
325+
326+ # cfaResult[["lav"]] <- jaspSem::lavBootstrap(cfaResult[["lav"]], options$bootstrapSamples,
327+ # standard = options[["standardized"]] != "none", typeStd = type)
328+
329+ cfaResult [[" lav" ]] <- lavBootstrap(cfaResult [[" lav" ]], options $ bootstrapSamples ,
330+ standard = options [[" standardized" ]] != " none" , typeStd = type )
327331 }
328332
329333 # Save cfaResult as state so it's available even when opts don't change
@@ -961,7 +965,7 @@ confirmatoryFactorAnalysisInternal <- function(jaspResults, dataset, options, ..
961965 }
962966
963967 # Intercepts ----
964- if (options $ meanStructure ) {
968+ if (options $ meanStructure || options $ group != " " ) {
965969
966970 if (options $ group != " " ) {
967971
@@ -1530,29 +1534,20 @@ confirmatoryFactorAnalysisInternal <- function(jaspResults, dataset, options, ..
15301534
15311535}
15321536
1533- # delete once jaspSem is merged
1534- lavBootstrap <- function (fit , samples = 1000 , standard = FALSE , typeStd = NULL ) {
1535- # Run bootstrap, track progress with progress bar
1536- # Notes: faulty runs are simply ignored
1537- # recommended: add a warning if not all boot samples are successful
1538- # fit <- lavBootstrap(fit, samples = 1000)
1539- # if (nrow(fit@boot$coef) < 1000)
1540- # tab$addFootnote(gettextf("Not all bootstrap samples were successful: CI based on %.0f samples.", nrow(fit@boot$coef)),
1541- # "<em>Note.</em>")
1542-
1537+ # delete this once jaspSem is merged
1538+ lavBootstrap <- function (fit , samples = 1000 , standard = FALSE , typeStd = NULL , iseed = NULL ) {
15431539
1544- coef_with_callback <- function (lav_object ) {
1540+ coefWithCallback <- function (lav_object ) {
15451541 # Progress bar is ticked every time coef() is evaluated, which happens once on the main object:
15461542 # https://github.com/yrosseel/lavaan/blob/77a568a574e4113245e2f6aff1d7c3120a26dd90/R/lav_bootstrap.R#L107
15471543 # and then every time on a successful bootstrap:
15481544 # https://github.com/yrosseel/lavaan/blob/77a568a574e4113245e2f6aff1d7c3120a26dd90/R/lav_bootstrap.R#L375
15491545 # i.e., samples + 1 times
15501546 progressbarTick()
1551-
15521547 return (lavaan :: coef(lav_object ))
15531548 }
15541549
1555- coef_with_callback_std <- function (lav_object , typeStd ) {
1550+ coefWithCallbackStd <- function (lav_object , typeStd ) {
15561551 std <- lavaan :: standardizedSolution(lav_object , type = typeStd )
15571552 out <- std $ est.std
15581553
@@ -1564,38 +1559,39 @@ lavBootstrap <- function(fit, samples = 1000, standard = FALSE, typeStd = NULL)
15641559 startProgressbar(samples + 1 )
15651560
15661561 if (! standard ) {
1567- bootres <- lavaan :: bootstrapLavaan(object = fit , R = samples , FUN = coef_with_callback )
1562+ bootres <- lavaan :: bootstrapLavaan(object = fit , R = samples , FUN = coefWithCallback , iseed = iseed )
15681563 } else {
1569- bootres <- lavaan :: bootstrapLavaan(object = fit , R = samples , FUN = coef_with_callback_std , typeStd = typeStd )
1564+ bootres <- lavaan :: bootstrapLavaan(object = fit , R = samples , FUN = coefWithCallbackStd , typeStd = typeStd , iseed = iseed )
15701565 }
15711566
15721567 # Add the bootstrap samples to the fit object
15731568 fit @ boot <- list (coef = bootres )
15741569 fit @ Options $ se <- " bootstrap"
15751570
15761571 # exclude error bootstrap runs
1577- err_id <- attr(fit @ boot $ coef , " error.idx" )
1578- if (length(err_id ) > 0L ) {
1579- fit @ boot $ coef <- fit @ boot $ coef [- err_id , , drop = FALSE ]
1572+ errId <- attr(fit @ boot $ coef , " error.idx" )
1573+ if (length(errId ) > 0L ) {
1574+ fit @ boot $ coef <- fit @ boot $ coef [- errId , , drop = FALSE ]
15801575 }
15811576
1582- # we actually need the SEs from the bootstrap not the SEs from ML or something
1577+ # we actually need the SEs from the bootstrap not the SEs from ML or some other estimator
15831578 N <- nrow(fit @ boot $ coef )
1579+ P <- ncol(fit @ boot $ coef )
1580+ freePars <- which(fit @ ParTable $ free != 0 )
15841581
15851582 # we multiply the var by (n-1)/n because lavaan actually uses n for the variance instead of n-1
15861583 if (! standard ) {
15871584 # for unstandardized
1588- fit @ ParTable $ se [fit @ ParTable $ free != 0 ] <- apply(fit @ boot $ coef , 2 , sd ) * sqrt((N - 1 )/ N )
1585+ fit @ ParTable $ se [freePars ] <- apply(fit @ boot $ coef , 2 , sd ) * sqrt((N - 1 )/ N )
15891586 } else {
1590- fit @ ParTable $ se <- apply(fit @ boot $ coef , 2 , sd ) * sqrt((N - 1 )/ N )
1591- # the standardized solution gives all estimates not only the unconstrained, so we need to change
1592- # the free prameters in the partable and also change the estimate
1593- fit @ ParTable $ free <- seq_len(ncol(fit @ boot $ coef ))
1587+ # when there are contraints the parameterestimates() function expects a boot sample for the free parameters only
1588+ fit @ ParTable $ se [1 : P ] <- apply(fit @ boot $ coef , 2 , sd ) * sqrt((N - 1 )/ N )
1589+ fit @ boot $ coef <- fit @ boot $ coef [, freePars , drop = FALSE ]
15941590 std <- lavaan :: standardizedSolution(fit , type = typeStd )
1595- fit @ ParTable $ est <- std $ est.std
1591+ # for the standardized output we also replace some constrained elements
1592+ fit @ ParTable $ est [1 : P ] <- std $ est.std
15961593 }
15971594
1598-
15991595 return (fit )
16001596}
16011597
0 commit comments