diff --git a/.gitignore b/.gitignore
index 27cf22d6..78a85598 100644
--- a/.gitignore
+++ b/.gitignore
@@ -55,3 +55,13 @@ renv_build.R
# dev mode files
jasp_dev_work_dir/
+
+# AI assistant configs
+.claude/
+.mcp.json
+.vscode/mcp.json
+.github/copilot-instructions.md
+.github/instructions/
+
+# test problem files
+tests/testthat/_problems/
diff --git a/NEWS.md b/NEWS.md
index 7fa7a0b8..9917e800 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,5 +1,13 @@
# jaspSem (development version)
+## [Pull Request #360](https://github.com/jasp-stats/jaspSem/pull/360)
+- Replace help files with inline `info` fields on all QML controls across SEM, Mediation Analysis, MIMIC, PLS-SEM, and MNLFA
+- Standardize all table, plot, and container titles to Title Case across all R files
+- Wrap missing user-visible strings in `gettext()` for internationalization
+- Fix `initCollapsed` parameter placement in PLS-SEM correlation containers
+- Enable `preloadData` for all analyses
+- Fix "Residuals" → "Residual" in covariance matrix titles for consistency
+
## [Pull Request #248](https://github.com/jasp-stats/jaspSem/pull/248):
- Major changes to SEM:
- ordinal data fully supported
diff --git a/R/common.R b/R/common.R
index 769232a5..433463d7 100644
--- a/R/common.R
+++ b/R/common.R
@@ -587,7 +587,8 @@ lavBootstrap <- function(fit, samples = 1000, standard = FALSE, typeStd = NULL,
.additionalFitTables <- function(modelContainer, dataset, options, ready) {
- fitinds <- createJaspTable(gettext("Fit indices"))
+ fitinds <- createJaspTable(gettext("Fit Indices"))
+ fitinds$info <- gettext("Detailed model fit indices. Includes incremental fit indices (CFI, TLI, NFI) comparing the model to the independence model, parsimony-adjusted indices, the RMSEA with confidence interval and close-fit test, SRMR, and information criteria (AIC, BIC, log-likelihood). CFI and TLI values above 0.95, RMSEA below 0.06, and SRMR below 0.08 suggest good fit.")
fitinds$dependOn("additionalFitMeasures")
fitinds$addColumnInfo(name = "index", title = gettext("Index"), type = "string")
diff --git a/R/lgcm.R b/R/lgcm.R
index 7830f80d..9344c5ff 100644
--- a/R/lgcm.R
+++ b/R/lgcm.R
@@ -223,13 +223,15 @@ LatentGrowthCurveInternal <- function(jaspResults, dataset, options, ...) {
.lgcmFitTable <- function(modelContainer, dataset, options, ready) {
if (!is.null(modelContainer[["maintab"]])) return()
- maintab <- createJaspTable(gettext("Chi-square test"))
- maintab$addColumnInfo(name = "mod", title = "Model", type = "string")
+ maintab <- createJaspTable(gettext("Chi-Square Test"))
+ maintab$info <- gettext("Chi-square goodness-of-fit test comparing the growth curve model to the baseline (independence) model. A non-significant p-value for the growth curve model suggests adequate fit to the data.")
+ maintab$addColumnInfo(name = "mod", title = gettext("Model"), type = "string")
maintab$addColumnInfo(name = "chisq", title = "\u03a7\u00b2", type = "number", format = "dp:3")
- maintab$addColumnInfo(name = "df", title = "df", type = "integer")
- maintab$addColumnInfo(name = "pvalue", title = "p", type = "number", format = "dp:3;p:.001")
+ maintab$addColumnInfo(name = "df", title = gettext("df"), type = "integer")
+ maintab$addColumnInfo(name = "pvalue", title = gettext("p"), type = "number", format = "dp:3;p:.001")
- modelContainer[["maintab"]] <- createJaspContainer("Model fit")
+ modelContainer[["maintab"]] <- createJaspContainer(gettext("Model Fit"))
+ modelContainer[["maintab"]]$info <- gettext("Model fit statistics for the latent growth curve model.")
modelContainer[["maintab"]]$position <- 1
modelContainer[["maintab"]][["chisqtab"]] <- maintab
@@ -264,8 +266,9 @@ LatentGrowthCurveInternal <- function(jaspResults, dataset, options, ...) {
partabs <- if (!is.null(modelContainer[["partabs"]])) {
modelContainer[["partabs"]]
} else {
- modelContainer[["partabs"]] <- createJaspContainer(gettext("Parameter estimates"))
+ modelContainer[["partabs"]] <- createJaspContainer(gettext("Parameter Estimates"))
}
+ partabs$info <- gettext("Parameter estimates for the latent growth curve model, including growth factor means, variances, covariances, and regression coefficients.")
partabs$dependOn(c("ciLevel", "bootstrapCiType"))
partabs$position <- 2
@@ -273,33 +276,35 @@ LatentGrowthCurveInternal <- function(jaspResults, dataset, options, ...) {
# create tables
# latent curve
- latcur <- createJaspTable("Latent curve")
+ latcur <- createJaspTable(gettext("Latent Curve"))
+ latcur$info <- gettext("Means and variances of the latent growth factors (e.g., intercept, slope). The intercept mean represents the average starting level, the slope mean the average rate of change, and their variances reflect individual differences in starting level and change.")
latcur$addColumnInfo("component", title = gettext("Component"), type = "string", combine = TRUE)
latcur$addColumnInfo("param", title = gettext("Parameter"), type = "string")
latcur$addColumnInfo("est", title = estTitle, type = "number", format = "dp:3")
- latcur$addColumnInfo("se" , title = gettext("Std. error"), type = "number", format = "dp:3")
+ latcur$addColumnInfo("se" , title = gettext("Std. Error"), type = "number", format = "dp:3")
latcur$addColumnInfo("zval", title = gettext("z-value"), type = "number", format = "dp:3")
latcur$addColumnInfo("pval", title = gettext("p"), type = "number", format = "dp:3;p:.001")
latcur$addColumnInfo("cilo", title = gettext("Lower"), type = "number", format = "dp:3",
overtitle = gettextf("%s%% Confidence Interval", options$ciLevel * 100))
- latcur$addColumnInfo("ciup", title = "Upper" , type = "number", format = "dp:3",
+ latcur$addColumnInfo("ciup", title = gettext("Upper") , type = "number", format = "dp:3",
overtitle = gettextf("%s%% Confidence Interval", options$ciLevel * 100))
modelContainer[["partabs"]][["latcur"]] <- latcur
# covariance
if (options[["covaryingLatentCurve"]]) {
- latcov <- createJaspTable(gettext("Latent covariances"))
+ latcov <- createJaspTable(gettext("Latent Covariances"))
+ latcov$info <- gettext("Covariances between latent growth factors. For example, a positive intercept-slope covariance indicates that individuals with higher starting values tend to show steeper change over time.")
latcov$addColumnInfo("lhs", title = "", type = "string")
latcov$addColumnInfo("sep", title = "", type = "separator")
latcov$addColumnInfo("rhs", title = "", type = "string")
latcov$addColumnInfo("est", title = estTitle, type = "number", format = "dp:3")
- latcov$addColumnInfo("se" , title = gettext("Std. error"), type = "number", format = "dp:3")
+ latcov$addColumnInfo("se" , title = gettext("Std. Error"), type = "number", format = "dp:3")
latcov$addColumnInfo("zval", title = gettext("z-value"), type = "number", format = "dp:3")
latcov$addColumnInfo("pval", title = gettext("p"), type = "number", format = "dp:3;p:.001")
latcov$addColumnInfo("cilo", title = gettext("Lower"), type = "number", format = "dp:3",
overtitle = gettextf("%s%% Confidence Interval", options$ciLevel * 100))
- latcov$addColumnInfo("ciup", title = "Upper" , type = "number", format = "dp:3",
+ latcov$addColumnInfo("ciup", title = gettext("Upper") , type = "number", format = "dp:3",
overtitle = gettextf("%s%% Confidence Interval", options$ciLevel * 100))
modelContainer[["partabs"]][["latcov"]] <- latcov
@@ -308,16 +313,17 @@ LatentGrowthCurveInternal <- function(jaspResults, dataset, options, ...) {
# regressions
if (length(c(options[["regressions"]], options[["categorical"]])) > 0) {
- latreg <- createJaspTable("Regressions")
+ latreg <- createJaspTable(gettext("Regressions"))
+ latreg$info <- gettext("Regression coefficients of covariates predicting the latent growth factors. These show how external variables relate to individual differences in initial level and rate of change.")
latreg$addColumnInfo("component", title = gettext("Component"), type = "string", combine = TRUE)
latreg$addColumnInfo("predictor", title = gettext("Predictor"), type = "string")
latreg$addColumnInfo("est", title = estTitle, type = "number", format = "dp:3")
- latreg$addColumnInfo("se" , title = gettext("Std. error"), type = "number", format = "dp:3")
+ latreg$addColumnInfo("se" , title = gettext("Std. Error"), type = "number", format = "dp:3")
latreg$addColumnInfo("zval", title = gettext("z-value"), type = "number", format = "dp:3")
latreg$addColumnInfo("pval", title = gettext("p"), type = "number", format = "dp:3;p:.001")
latreg$addColumnInfo("cilo", title = gettext("Lower"), type = "number", format = "dp:3",
overtitle = gettextf("%s%% Confidence Interval", options$ciLevel * 100))
- latreg$addColumnInfo("ciup", title = "Upper" , type = "number", format = "dp:3",
+ latreg$addColumnInfo("ciup", title = gettext("Upper") , type = "number", format = "dp:3",
overtitle = gettextf("%s%% Confidence Interval", options$ciLevel * 100))
@@ -325,15 +331,16 @@ LatentGrowthCurveInternal <- function(jaspResults, dataset, options, ...) {
}
# residual variances
- resvar <- createJaspTable("Residual variances")
+ resvar <- createJaspTable(gettext("Residual Variances"))
+ resvar$info <- gettext("Time-specific residual variances of the observed variables. These represent measurement error plus occasion-specific variance not captured by the growth factors. Negative values may indicate model misspecification.")
resvar$addColumnInfo("var", title = gettext("Variable"), type = "string")
resvar$addColumnInfo("est", title = estTitle, type = "number", format = "dp:3")
- resvar$addColumnInfo("se" , title = gettext("Std. error"), type = "number", format = "dp:3")
+ resvar$addColumnInfo("se" , title = gettext("Std. Error"), type = "number", format = "dp:3")
resvar$addColumnInfo("zval", title = gettext("z-value"), type = "number", format = "dp:3")
resvar$addColumnInfo("pval", title = gettext("p"), type = "number", format = "dp:3;p:.001")
resvar$addColumnInfo("cilo", title = gettext("Lower"), type = "number", format = "dp:3",
overtitle = gettextf("%s%% Confidence Interval", options$ciLevel * 100))
- resvar$addColumnInfo("ciup", title = "Upper" , type = "number", format = "dp:3",
+ resvar$addColumnInfo("ciup", title = gettext("Upper") , type = "number", format = "dp:3",
overtitle = gettextf("%s%% Confidence Interval", options$ciLevel * 100))
modelContainer[["partabs"]][["resvar"]] <- resvar
@@ -448,8 +455,9 @@ LatentGrowthCurveInternal <- function(jaspResults, dataset, options, ...) {
if (!options[["rSquared"]] || !is.null(modelContainer[["rsquared"]])) return()
tabr2 <- createJaspTable(gettext("R-Squared"))
+ tabr2$info <- gettext("Proportion of variance in each observed variable at each time point explained by the latent growth factors.")
tabr2$position <- 3.5
- tabr2$addColumnInfo(name = "__var__", title = "Variable", type = "string")
+ tabr2$addColumnInfo(name = "__var__", title = gettext("Variable"), type = "string")
tabr2$addColumnInfo(name = "rsq", title = "R\u00B2", type = "number", format = "sf:4;dp:3")
tabr2$dependOn("rSquared")
modelContainer[["rsquared"]] <- tabr2
@@ -466,7 +474,8 @@ LatentGrowthCurveInternal <- function(jaspResults, dataset, options, ...) {
.lgcmImpliedCovTable <- function(modelContainer, dataset, options, ready) {
if (!options[["impliedCovariance"]]) return()
- tab <- createJaspTable(gettext("Implied covariance matrix"))
+ tab <- createJaspTable(gettext("Implied Covariance Matrix"))
+ tab$info <- gettext("Model-implied covariance matrix from the latent growth curve model.")
tab$dependOn("impliedCovariance")
tab$position <- 4
modelContainer[["impliedCovTab"]] <- tab
@@ -489,7 +498,8 @@ LatentGrowthCurveInternal <- function(jaspResults, dataset, options, ...) {
.lgcmResidualCovTable <- function(modelContainer, dataset, options, ready) {
if (!options[["residualCovariance"]]) return()
- tab <- createJaspTable(gettext("Residual covariance matrix"))
+ tab <- createJaspTable(gettext("Residual Covariance Matrix"))
+ tab$info <- gettext("Difference between the observed and model-implied covariance matrices. Small residuals indicate the growth curve model adequately reproduces the observed covariances.")
tab$dependOn("residualCovariance")
tab$position <- 5
modelContainer[["rescov"]] <- tab
@@ -512,7 +522,8 @@ LatentGrowthCurveInternal <- function(jaspResults, dataset, options, ...) {
.lgcmCurvePlot <- function(modelContainer, dataset, options, ready) {
if (!options[["curvePlot"]] || !is.null(modelContainer[["curveplot"]])) return()
- curveplot <- createJaspPlot(title = gettext("Curve plot"), width = 480, height = 320)
+ curveplot <- createJaspPlot(title = gettext("Curve Plot"), width = 480, height = 320)
+ curveplot$info <- gettext("Individual predicted growth trajectories over time. Each line represents a participant's estimated trajectory based on the latent growth factors.")
curveplot$dependOn(c("curvePlot", "curvePlotCategorical", "curvePlotMaxLines", "colorPalette"))
curveplot$position <- 8
modelContainer[["curveplot"]] <- curveplot
@@ -589,7 +600,8 @@ LatentGrowthCurveInternal <- function(jaspResults, dataset, options, ...) {
.lgcmPathPlot <- function(modelContainer, dataset, options, ready) {
if (!options$pathPlot || !is.null(modelContainer[["pathplot"]])) return()
- modelContainer[["pathplot"]] <- createJaspPlot(title = gettext("Model plot"), height = 500, width = 640)
+ modelContainer[["pathplot"]] <- createJaspPlot(title = gettext("Model Plot"), height = 500, width = 640)
+ modelContainer[["pathplot"]]$info <- gettext("Path diagram of the latent growth curve model showing the growth factors, their loadings on observed time points, and any covariates.")
modelContainer[["pathplot"]]$dependOn(c("pathPlot", "pathPlotMean", "pathPlotParameter"))
modelContainer[["pathplot"]]$position <- 9
@@ -623,16 +635,17 @@ LatentGrowthCurveInternal <- function(jaspResults, dataset, options, ...) {
text = .lgcmOptionsToMod(options, FALSE),
class = "jasp-code",
position = 10,
- title = "Model Syntax",
+ title = gettext("Model Syntax"),
dependencies = "syntax"
)
+ modelContainer[["model_syntax"]]$info <- gettext("The lavaan model syntax for the growth curve model, showing fixed factor loadings that define the growth trajectory shape.")
}
# Unused functions ----
.lgcmMisfitPlot <- function(modelContainer, dataset, options, ready) {
if (!options[["misfitPlot"]] || !is.null(modelContainer[["misfitplot"]])) return()
wh <- 50 + 50*length(options[["variables"]])
- misplot <- createJaspPlot(title = gettext("Misfit plot"), width = wh, height = wh)
+ misplot <- createJaspPlot(title = gettext("Misfit Plot"), width = wh, height = wh)
misplot$dependOn("misfitPlot")
misplot$position <- 9
modelContainer[["misfitplot"]] <- misplot
diff --git a/R/mediationanalysis.R b/R/mediationanalysis.R
index fac7d0c9..02fb7f31 100644
--- a/R/mediationanalysis.R
+++ b/R/mediationanalysis.R
@@ -274,7 +274,8 @@ MediationAnalysisInternal <- function(jaspResults, dataset, options, ...) {
.medParTable <- function(modelContainer, dataset, options, ready) {
if (!is.null(modelContainer[["parest"]])) return()
- modelContainer[["parest"]] <- pecont <- createJaspContainer(gettext("Parameter estimates"))
+ modelContainer[["parest"]] <- pecont <- createJaspContainer(gettext("Parameter Estimates"))
+ pecont$info <- gettext("Parameter estimates from the mediation model, organized by direct effects, indirect effects, and total effects.")
pecont$dependOn(options = c("ciLevel", "bootstrapCiType"))
pecont$position <- 0
@@ -282,12 +283,13 @@ MediationAnalysisInternal <- function(jaspResults, dataset, options, ...) {
## direct effects
dirtab <- createJaspTable(title = gettext("Direct effects"))
+ dirtab$info <- gettext("Direct effects of predictors on outcomes, bypassing all mediators (the c or c' path). A significant direct effect indicates that the predictor influences the outcome independently of the mediation pathway.")
dirtab$addColumnInfo(name = "lhs", title = "", type = "string")
dirtab$addColumnInfo(name = "op", title = "", type = "string")
dirtab$addColumnInfo(name = "rhs", title = "", type = "string")
dirtab$addColumnInfo(name = "est", title = estTitle, type = "number", format = "sf:4;dp:3")
- dirtab$addColumnInfo(name = "se", title = gettext("Std. error"), type = "number", format = "sf:4;dp:3")
+ dirtab$addColumnInfo(name = "se", title = gettext("Std. Error"), type = "number", format = "sf:4;dp:3")
dirtab$addColumnInfo(name = "z", title = gettext("z-value"), type = "number", format = "sf:4;dp:3")
dirtab$addColumnInfo(name = "pvalue", title = gettext("p"), type = "number", format = "dp:3;p:.001")
dirtab$addColumnInfo(name = "ci.lower", title = gettext("Lower"), type = "number", format = "sf:4;dp:3",
@@ -300,6 +302,7 @@ MediationAnalysisInternal <- function(jaspResults, dataset, options, ...) {
## indirect effects
indtab <- createJaspTable(title = gettext("Indirect effects"))
+ indtab$info <- gettext("Indirect effects of predictors on outcomes transmitted through mediators. Each indirect effect is the product of the path coefficients along the mediation pathway (a \u00d7 b). A significant indirect effect indicates that mediation occurs through that pathway.")
indtab$addColumnInfo(name = "x", title = "", type = "string")
indtab$addColumnInfo(name = "op1", title = "", type = "string")
@@ -307,7 +310,7 @@ MediationAnalysisInternal <- function(jaspResults, dataset, options, ...) {
indtab$addColumnInfo(name = "op2", title = "", type = "string")
indtab$addColumnInfo(name = "y", title = "", type = "string")
indtab$addColumnInfo(name = "est", title = estTitle, type = "number", format = "sf:4;dp:3")
- indtab$addColumnInfo(name = "se", title = gettext("Std. error"), type = "number", format = "sf:4;dp:3")
+ indtab$addColumnInfo(name = "se", title = gettext("Std. Error"), type = "number", format = "sf:4;dp:3")
indtab$addColumnInfo(name = "z", title = gettext("z-value"), type = "number", format = "sf:4;dp:3")
indtab$addColumnInfo(name = "pvalue", title = gettext("p"), type = "number", format = "dp:3;p:.001")
indtab$addColumnInfo(name = "ci.lower", title = gettext("Lower"), type = "number", format = "sf:4;dp:3",
@@ -318,13 +321,14 @@ MediationAnalysisInternal <- function(jaspResults, dataset, options, ...) {
pecont[["ind"]] <- indtab
## total effects
- tottab <- createJaspTable(title = "Total effects")
+ tottab <- createJaspTable(title = gettext("Total Effects"))
+ tottab$info <- gettext("Total effects combining the direct effect and all indirect effects for each predictor-outcome pair. The total effect equals the sum of the direct and indirect effects (c = c' + a \u00d7 b).")
tottab$addColumnInfo(name = "lhs", title = "", type = "string")
tottab$addColumnInfo(name = "op", title = "", type = "string")
tottab$addColumnInfo(name = "rhs", title = "", type = "string")
tottab$addColumnInfo(name = "est", title = estTitle, type = "number", format = "sf:4;dp:3")
- tottab$addColumnInfo(name = "se", title = gettext("Std. error"), type = "number", format = "sf:4;dp:3")
+ tottab$addColumnInfo(name = "se", title = gettext("Std. Error"), type = "number", format = "sf:4;dp:3")
tottab$addColumnInfo(name = "z", title = gettext("z-value"), type = "number", format = "sf:4;dp:3")
tottab$addColumnInfo(name = "pvalue", title = gettext("p"), type = "number", format = "dp:3;p:.001")
tottab$addColumnInfo(name = "ci.lower", title = gettext("Lower"), type = "number", format = "sf:4;dp:3",
@@ -432,6 +436,7 @@ MediationAnalysisInternal <- function(jaspResults, dataset, options, ...) {
if (!options[["totalIndirectEffect"]] || !length(options$mediators) > 1) return()
ttitab <- createJaspTable(title = gettext("Total indirect effects"))
+ ttitab$info <- gettext("Total indirect effects summed across all mediators for each predictor-outcome pair. When there are multiple mediators, this gives the combined strength of all indirect pathways.")
ttitab$dependOn("totalIndirectEffect")
estTitle <- ifelse(options[["standardizedEstimate"]], gettext("Std. estimate"), gettext("Estimate"))
@@ -440,7 +445,7 @@ MediationAnalysisInternal <- function(jaspResults, dataset, options, ...) {
ttitab$addColumnInfo(name = "op", title = "", type = "string")
ttitab$addColumnInfo(name = "rhs", title = "", type = "string")
ttitab$addColumnInfo(name = "est", title = estTitle, type = "number", format = "sf:4;dp:3")
- ttitab$addColumnInfo(name = "se", title = gettext("Std. error"), type = "number", format = "sf:4;dp:3")
+ ttitab$addColumnInfo(name = "se", title = gettext("Std. Error"), type = "number", format = "sf:4;dp:3")
ttitab$addColumnInfo(name = "z", title = gettext("z-value"), type = "number", format = "sf:4;dp:3")
ttitab$addColumnInfo(name = "pvalue", title = gettext("p"), type = "number", format = "dp:3;p:.001")
ttitab$addColumnInfo(name = "ci.lower", title = gettext("Lower"), type = "number", format = "sf:4;dp:3",
@@ -491,6 +496,7 @@ MediationAnalysisInternal <- function(jaspResults, dataset, options, ...) {
if (!options[["residualCovariance"]] || !length(c(options$mediators, options$outcomes)) > 2) return()
restab <- createJaspTable(title = gettext("Residual covariances"))
+ restab$info <- gettext("Estimated residual covariances between endogenous variables (mediators and outcomes). These represent shared variance not accounted for by the model's directed paths.")
restab$dependOn("residualCovariance")
estTitle <- ifelse(options[["standardizedEstimate"]], gettext("Std. estimate"), gettext("Estimate"))
@@ -499,7 +505,7 @@ MediationAnalysisInternal <- function(jaspResults, dataset, options, ...) {
restab$addColumnInfo(name = "op", title = "", type = "string")
restab$addColumnInfo(name = "rhs", title = "", type = "string")
restab$addColumnInfo(name = "est", title = estTitle, type = "number", format = "sf:4;dp:3")
- restab$addColumnInfo(name = "se", title = gettext("Std. error"), type = "number", format = "sf:4;dp:3")
+ restab$addColumnInfo(name = "se", title = gettext("Std. Error"), type = "number", format = "sf:4;dp:3")
restab$addColumnInfo(name = "z", title = gettext("z-value"), type = "number", format = "sf:4;dp:3")
restab$addColumnInfo(name = "pvalue", title = gettext("p"), type = "number", format = "dp:3;p:.001")
restab$addColumnInfo(name = "ci.lower", title = gettext("Lower"), type = "number", format = "sf:4;dp:3",
@@ -547,6 +553,7 @@ MediationAnalysisInternal <- function(jaspResults, dataset, options, ...) {
if (!options[["pathCoefficient"]]) return()
pathtab <- createJaspTable(title = gettext("Path coefficients"))
+ pathtab$info <- gettext("Individual path coefficients in the mediation model. These include the a paths (predictor to mediator) and b paths (mediator to outcome), which constitute the building blocks of indirect effects.")
pathtab$dependOn("pathCoefficient")
estTitle <- ifelse(options[["standardizedEstimate"]], gettext("Std. estimate"), gettext("Estimate"))
@@ -555,7 +562,7 @@ MediationAnalysisInternal <- function(jaspResults, dataset, options, ...) {
pathtab$addColumnInfo(name = "op", title = "", type = "string")
pathtab$addColumnInfo(name = "rhs", title = "", type = "string")
pathtab$addColumnInfo(name = "est", title = estTitle, type = "number", format = "sf:4;dp:3")
- pathtab$addColumnInfo(name = "se", title = gettext("Std. error"), type = "number", format = "sf:4;dp:3")
+ pathtab$addColumnInfo(name = "se", title = gettext("Std. Error"), type = "number", format = "sf:4;dp:3")
pathtab$addColumnInfo(name = "z", title = gettext("z-value"), type = "number", format = "sf:4;dp:3")
pathtab$addColumnInfo(name = "pvalue", title = gettext("p"), type = "number", format = "dp:3;p:.001")
pathtab$addColumnInfo(name = "ci.lower", title = gettext("Lower"), type = "number", format = "sf:4;dp:3",
@@ -615,6 +622,7 @@ MediationAnalysisInternal <- function(jaspResults, dataset, options, ...) {
if (!options$rSquared || !is.null(modelContainer[["rsquared"]])) return()
tabr2 <- createJaspTable(gettext("R-Squared"))
+ tabr2$info <- gettext("Proportion of variance in each mediator and outcome variable explained by its predictors in the mediation model.")
tabr2$addColumnInfo(name = "__var__", title = "", type = "string")
tabr2$addColumnInfo(name = "rsq", title = "R\u00B2", type = "number", format = "sf:4;dp:3")
tabr2$dependOn(options = "rSquared")
@@ -632,7 +640,8 @@ MediationAnalysisInternal <- function(jaspResults, dataset, options, ...) {
.medPathPlot <- function(modelContainer, options, ready) {
if (!options$pathPlot || !ready || !is.null(modelContainer[["plot"]])) return()
- plt <- createJaspPlot(title = gettext("Path plot"), width = 600, height = 400)
+ plt <- createJaspPlot(title = gettext("Path Plot"), width = 600, height = 400)
+ plt$info <- gettext("Visual representation of the mediation model showing predictors, mediators, outcomes, directed paths, and (optionally) parameter estimates.")
plt$dependOn(options = c("pathPlot", "pathPlotParameter", "pathPlotLegend"))
plt$position <- 2
@@ -749,6 +758,7 @@ MediationAnalysisInternal <- function(jaspResults, dataset, options, ...) {
.medSyntax <- function(modelContainer, options, ready) {
if (!options$syntax || !ready) return()
modelContainer[["syntax"]] <- createJaspHtml(.medToLavMod(options, FALSE), class = "jasp-code", title = gettext("Model syntax"))
+ modelContainer[["syntax"]]$info <- gettext("The lavaan model syntax automatically generated from the mediation analysis specification. This shows the exact model fitted, including labeled direct and indirect effect parameters.")
modelContainer[["syntax"]]$dependOn("syntax")
modelContainer[["syntax"]]$position <- 3
}
diff --git a/R/mimic.R b/R/mimic.R
index 10f6aa67..db2e7696 100644
--- a/R/mimic.R
+++ b/R/mimic.R
@@ -195,7 +195,8 @@ MIMICInternal <- function(jaspResults, dataset, options, ...) {
.mimicFitTable <- function(modelContainer, dataset, options, ready) {
if (!is.null(modelContainer[["fittab"]])) return()
- fittab <- createJaspTable(title = gettext("Chi-square test"))
+ fittab <- createJaspTable(title = gettext("Chi-Square Test"))
+ fittab$info <- gettext("Chi-square goodness-of-fit test for the MIMIC model. Both the baseline (independence) model and the factor model with predictors are shown. A non-significant chi-square for the factor model indicates adequate fit.")
fittab$position <- 0
fittab$addColumnInfo(name="Model", title = "", type = "string")
@@ -235,7 +236,8 @@ MIMICInternal <- function(jaspResults, dataset, options, ...) {
.mimicParTable <- function(modelContainer, options, ready) {
if (!is.null(modelContainer[["parest"]])) return()
- modelContainer[["parest"]] <- pecont <- createJaspContainer(gettext("Parameter estimates"))
+ modelContainer[["parest"]] <- pecont <- createJaspContainer(gettext("Parameter Estimates"))
+ pecont$info <- gettext("Parameter estimates for the MIMIC (Multiple Indicators, Multiple Causes) model. The model has observed predictors influencing a latent variable, which in turn is measured by observed indicators.")
pecont$dependOn(options = c("ciLevel", "bootstrapCiType"))
pecont$position <- 0.5
@@ -243,10 +245,11 @@ MIMICInternal <- function(jaspResults, dataset, options, ...) {
## betas
bettab <- createJaspTable(title = gettext("Predictor coefficients"))
+ bettab$info <- gettext("Regression coefficients of the observed predictor (cause) variables on the latent variable. These represent the direct effects of each predictor on the latent construct.")
bettab$addColumnInfo(name = "rhs", title = gettext("Predictor"), type = "string")
bettab$addColumnInfo(name = "est", title = estTitle, type = "number", format = "sf:4;dp:3")
- bettab$addColumnInfo(name = "se", title = gettext("Std. error"), type = "number", format = "sf:4;dp:3")
+ bettab$addColumnInfo(name = "se", title = gettext("Std. Error"), type = "number", format = "sf:4;dp:3")
bettab$addColumnInfo(name = "z", title = gettext("z-value"), type = "number", format = "sf:4;dp:3")
bettab$addColumnInfo(name = "pvalue", title = gettext("p"), type = "number", format = "dp:3;p:.001")
bettab$addColumnInfo(name = "ci.lower", title = gettext("Lower"), type = "number", format = "sf:4;dp:3",
@@ -259,10 +262,11 @@ MIMICInternal <- function(jaspResults, dataset, options, ...) {
## lambdas
lamtab <- createJaspTable(title = gettext("Indicator coefficients"))
+ lamtab$info <- gettext("Factor loadings of the latent variable on its observed indicators. These represent how strongly each indicator reflects the underlying latent construct.")
lamtab$addColumnInfo(name = "rhs", title = gettext("Indicator"), type = "string")
lamtab$addColumnInfo(name = "est", title = estTitle, type = "number", format = "sf:4;dp:3")
- lamtab$addColumnInfo(name = "se", title = gettext("Std. error"), type = "number", format = "sf:4;dp:3")
+ lamtab$addColumnInfo(name = "se", title = gettext("Std. Error"), type = "number", format = "sf:4;dp:3")
lamtab$addColumnInfo(name = "z", title = gettext("z-value"), type = "number", format = "sf:4;dp:3")
lamtab$addColumnInfo(name = "pvalue", title = gettext("p"), type = "number", format = "dp:3;p:.001")
lamtab$addColumnInfo(name = "ci.lower", title = gettext("Lower"), type = "number", format = "sf:4;dp:3",
@@ -323,6 +327,7 @@ MIMICInternal <- function(jaspResults, dataset, options, ...) {
if (!options$rSquared || !is.null(modelContainer[["rsquared"]])) return()
tabr2 <- createJaspTable(gettext("R-Squared"))
+ tabr2$info <- gettext("Proportion of variance explained in the latent variable (by the predictors) and in each indicator (by the latent variable).")
tabr2$addColumnInfo(name = "__var__", title = "", type = "string")
tabr2$addColumnInfo(name = "rsq", title = "R\u00B2", type = "number", format = "sf:4;dp:3")
tabr2$dependOn(options = "rSquared")
@@ -340,7 +345,8 @@ MIMICInternal <- function(jaspResults, dataset, options, ...) {
.mimicPathPlot <- function(modelContainer, dataset, options, ready) {
if (!options$pathPlot || !ready || !is.null(modelContainer[["plot"]])) return()
- plt <- createJaspPlot(title = gettext("Path plot"), width = 600, height = 400)
+ plt <- createJaspPlot(title = gettext("Path Plot"), width = 600, height = 400)
+ plt$info <- gettext("Path diagram of the MIMIC model showing observed predictors (causes), the latent variable, and its observed indicators.")
plt$dependOn(options = c("pathPlot", "pathPlotParameter", "pathPlotLegend"))
plt$position <- 2
@@ -380,6 +386,7 @@ MIMICInternal <- function(jaspResults, dataset, options, ...) {
.mimicSyntax <- function(modelContainer, options, ready) {
if (!options$syntax || !ready) return()
modelContainer[["syntax"]] <- createJaspHtml(.mimicToLavMod(options, FALSE), class = "jasp-code", title = gettext("Model syntax"))
+ modelContainer[["syntax"]]$info <- gettext("The lavaan model syntax specifying the MIMIC model structure, including the measurement model and the regression of the latent variable on the predictors.")
modelContainer[["syntax"]]$dependOn("syntax")
modelContainer[["syntax"]]$position <- 3
}
diff --git a/R/moderatedNonLinearFactorAnalysis.R b/R/moderatedNonLinearFactorAnalysis.R
index 28fe96c3..c861a6a0 100644
--- a/R/moderatedNonLinearFactorAnalysis.R
+++ b/R/moderatedNonLinearFactorAnalysis.R
@@ -427,6 +427,7 @@ ModeratedNonLinearFactorAnalysisInternal <- function(jaspResults, dataset, optio
if (!options[["checkModelFitPerGroup"]]) return()
fitPerGroupTable <- createJaspTable(gettext("Fit per Group Test"))
+ fitPerGroupTable$info <- gettext("CFA fit statistics computed separately for each group defined by the moderator. This checks whether the baseline factor model fits adequately within each group before testing invariance.")
fitPerGroupTable$addColumnInfo(name = "model", title = gettext("Group Model"), type = "string")
groupContainer <- createJaspContainer()
@@ -489,6 +490,7 @@ ModeratedNonLinearFactorAnalysisInternal <- function(jaspResults, dataset, optio
return()
invFitTable <- createJaspTable(gettext("Global Invariance Fit"))
+ invFitTable$info <- gettext("Comparison of MNLFA invariance models (configural, metric, scalar, strict) using -2 log-likelihood difference tests. Significant differences indicate that the more constrained model fits significantly worse, suggesting non-invariance at that level.")
invFitTable$addColumnInfo(name = "type", title = gettext("Type"), type = "string")
invFitTable$addColumnInfo(name = "Npar", title = gettext("n(Par)"), type = "integer")
# invFitTable$addColumnInfo(name = "df", title = gettext("df"), type = "integer")
@@ -515,6 +517,7 @@ ModeratedNonLinearFactorAnalysisInternal <- function(jaspResults, dataset, optio
}
invFitTable <- createJaspTable(gettext("Global Invariance Fit"))
+ invFitTable$info <- gettext("Comparison of MNLFA invariance models (configural, metric, scalar, strict) using -2 log-likelihood difference tests. Significant differences indicate that the more constrained model fits significantly worse, suggesting non-invariance at that level.")
jaspResults[["fitContainer"]][["invFitTable"]] <- invFitTable
invFitTable$addColumnInfo(name = "type", title = gettext("Type"), type = "string")
@@ -681,6 +684,7 @@ ModeratedNonLinearFactorAnalysisInternal <- function(jaspResults, dataset, optio
if (length(results) == 0) return()
globalParameterContainer <- createJaspContainer(gettext("Parameter Estimates"), initCollapsed = TRUE)
+ globalParameterContainer$info <- gettext("Parameter estimates from the MNLFA invariance models. Moderation effects show how each parameter varies as a function of the moderator variable. Estimates on 'Effect' rows represent the linear change in the parameter per unit change in the moderator.")
globalParameterContainer$position <- 3
# NEW: get nested paths for moderation include list (same trick as before)
@@ -747,6 +751,7 @@ ModeratedNonLinearFactorAnalysisInternal <- function(jaspResults, dataset, optio
allLoads <- loadPosition | loadPositionNoMod
if (sum(loadPosition) + sum(loadPositionNoMod) > 0) { # are loadings even there
loadTable <- createJaspTable(gettext("Loadings"))
+ loadTable$info <- gettext("Factor loadings and their moderation effects. Significant moderation effects indicate that the relationship between the latent factor and its indicator varies across levels of the moderator (metric non-invariance).")
cont[["loadTable"]] <- loadTable
loadTable$addColumnInfo(name = "factor", title = gettext("Factor"), type = "string", combine = TRUE)
loadTable$addColumnInfo(name = "indicator", title = gettext("Indicator"), type = "string", combine = TRUE)
@@ -793,6 +798,7 @@ ModeratedNonLinearFactorAnalysisInternal <- function(jaspResults, dataset, optio
intPosition <- grepl("^int_", parNames)
if (sum(intPosition) > 0) { # are intercepts even there
intTable <- createJaspTable(gettext("Intercepts"))
+ intTable$info <- gettext("Indicator intercepts and their moderation effects. Significant moderation effects indicate that the item difficulty or baseline level varies across the moderator (scalar non-invariance).")
cont[["intTable"]] <- intTable
intTable$addColumnInfo(name = "indicator", title = gettext("Indicator"), type = "string", combine = TRUE)
intTable$addColumnInfo(name = "effect", title = gettext("Effect"), type = "number")
@@ -843,6 +849,7 @@ ModeratedNonLinearFactorAnalysisInternal <- function(jaspResults, dataset, optio
resPosition <- grepl("^res_", parNames)
if (sum(resPosition) > 0) { # are residualVariances even specified
resTable <- createJaspTable(gettext("Residual Variances"))
+ resTable$info <- gettext("Indicator residual variances and their moderation effects. Estimates are on the log scale internally and back-transformed for display. Significant moderation indicates that measurement precision varies across the moderator (strict non-invariance).")
cont[["resTable"]] <- resTable
resTable$addColumnInfo(name = "indicator", title = gettext("Indicator"), type = "string", combine = TRUE)
resTable$addColumnInfo(name = "effect", title = gettext("Effect"), type = "number")
@@ -891,6 +898,7 @@ ModeratedNonLinearFactorAnalysisInternal <- function(jaspResults, dataset, optio
fvPosition <- grepl("^var_", parNames)
if (sum(fvPosition) > 0) { # are factor variances even specified
fvTable <- createJaspTable(gettext("Factor Variances"))
+ fvTable$info <- gettext("Latent factor variances and their moderation effects. Estimates are on the log scale internally and back-transformed for display. Significant moderation indicates that the spread of the latent trait changes across the moderator.")
cont[["fvTable"]] <- fvTable
fvTable$addColumnInfo(name = "factor", title = gettext("Factor"), type = "string", combine = TRUE)
fvTable$addColumnInfo(name = "effect", title = gettext("Effect"), type = "number")
@@ -937,6 +945,7 @@ ModeratedNonLinearFactorAnalysisInternal <- function(jaspResults, dataset, optio
fmPosition <- grepl("^mean_", parNames)
if (sum(fmPosition) > 0) { # are factor variances even specified
fmTable <- createJaspTable(gettext("Factor Means"))
+ fmTable$info <- gettext("Latent factor means and their moderation effects. Significant moderation indicates that the average level of the latent trait differs across the moderator.")
cont[["fmTable"]] <- fmTable
fmTable$addColumnInfo(name = "factor", title = gettext("Factor"), type = "string", combine = TRUE)
fmTable$addColumnInfo(name = "effect", title = gettext("Effect"), type = "number")
@@ -987,6 +996,7 @@ ModeratedNonLinearFactorAnalysisInternal <- function(jaspResults, dataset, optio
covPosition <- grepl("^rho_", parNames)
if (sum(covPosition) > 0) { # are factor covariances
covTable <- createJaspTable(gettext("Factor Covariances"))
+ covTable$info <- gettext("Latent factor covariances and their moderation effects. Significant moderation indicates that the relationship between latent factors varies across the moderator.")
cont[["covTable"]] <- covTable
covTable$addColumnInfo(name = "effect", title = gettext("Effect"), type = "number")
# covTable$addColumnInfo(name = "param", title = gettext("Parameter"), type = "string")
@@ -1021,6 +1031,7 @@ ModeratedNonLinearFactorAnalysisInternal <- function(jaspResults, dataset, optio
if (!is.null(jaspResults[["plotContainer"]])) return()
plotContainer <- createJaspContainer(gettext("Parameter Plots"))
+ plotContainer$info <- gettext("Plots showing how model parameters (loadings, intercepts, variances) vary as a function of the moderator variable. Each plot displays the estimated parameter value across the range of the moderator.")
plotContainer$position <- 3
plotContainer$dependOn(optionsFromObject = jaspResults[["mainContainer"]][["globalParameterContainer"]],
options = c("plotModelList", "includePlot"))
diff --git a/R/moderation.R b/R/moderation.R
deleted file mode 100644
index e69de29b..00000000
diff --git a/R/plssem.R b/R/plssem.R
index 6c60b86c..d6e81582 100644
--- a/R/plssem.R
+++ b/R/plssem.R
@@ -374,6 +374,7 @@ checkCSemModel <- function(model, availableVars) {
if (!options[["overallModelFit"]]) return()
fittab <- createJaspTable(title = gettext("Model Fit"))
+ fittab$info <- gettext("Overall model fit test using bootstrap-based distance measures. The test statistic is compared to a critical value obtained from bootstrapping. If the test statistic exceeds the critical value, the model is rejected at the chosen significance level.")
fittab$dependOn(optionsFromObject = modelContainer,
options = c("group", "omfBootstrapSamples", "omfSignificanceLevel", "saturatedStructuralModel",
"overallModelFit"))
@@ -468,6 +469,7 @@ checkCSemModel <- function(model, availableVars) {
# create container for parameter estimates
params <- createJaspContainer(gettext("Parameter Estimates"))
+ params$info <- gettext("Parameter estimates for the PLS-SEM model, including outer weights, outer loadings, inner model path coefficients, total effects, and residual correlations.")
params$position <- 1
params$dependOn(c("models", "ciLevel"))
@@ -494,6 +496,7 @@ checkCSemModel <- function(model, availableVars) {
# create weights table
weightTab <- createJaspTable(title = gettext("Weights"))
+ weightTab$info <- gettext("Outer weights relating observed indicators to their composite constructs. Weights determine how indicators are combined to form construct scores and reflect each indicator's relative contribution.")
if (options[["group"]] != "")
weightTab$addColumnInfo(name = "group", title = gettext("Group"), type = "string", combine = TRUE)
@@ -515,6 +518,7 @@ checkCSemModel <- function(model, availableVars) {
# create loadings table
loadingTab <- createJaspTable(title = gettext("Loadings"))
+ loadingTab$info <- gettext("Outer loadings (correlations) between indicators and their constructs. Loadings above 0.708 indicate that the construct explains more than 50%% of the indicator's variance.")
if (options[["group"]] != "")
loadingTab$addColumnInfo(name = "group", title = gettext("Group"), type = "string", combine = TRUE)
@@ -539,6 +543,7 @@ checkCSemModel <- function(model, availableVars) {
#create paths table
pathTab <- createJaspTable(title = gettext("Regression Coefficients"))
+ pathTab$info <- gettext("Inner model path coefficients between constructs. The f\u00B2 effect size indicates the substantive impact of removing each predictor: 0.02 (small), 0.15 (medium), 0.35 (large).")
if (options[["group"]] != "")
pathTab$addColumnInfo(name = "group", title = gettext("Group"), type = "string", combine = TRUE)
@@ -562,6 +567,7 @@ checkCSemModel <- function(model, availableVars) {
# create total effects table
totalTab <- createJaspTable(title = gettext("Total Effects"))
+ totalTab$info <- gettext("Total effects combining direct and all indirect paths between constructs.")
if (options[["group"]] != "")
totalTab$addColumnInfo(name = "group", title = gettext("Group"), type = "string", combine = TRUE)
@@ -583,6 +589,7 @@ checkCSemModel <- function(model, availableVars) {
# create residual correlation table
resCorTab <- createJaspTable(title = gettext("Residual Correlations"))
+ resCorTab$info <- gettext("Residual correlations between indicators after accounting for the construct model. These represent correlated measurement errors between indicator pairs.")
if (options[["group"]] != "")
resCorTab$addColumnInfo(name = "group", title = gettext("Group"), type = "string", combine = TRUE)
@@ -1083,6 +1090,7 @@ checkCSemModel <- function(model, availableVars) {
if (!options[["endogenousIndicatorPrediction"]] || !is.null(modelContainer[["predict"]])) return()
predict <- createJaspContainer(gettext("Endogenous Indicator Prediction"))
+ predict$info <- gettext("Cross-validated prediction of endogenous indicators using PLSpredict. The prediction metrics assess how well the PLS-SEM model predicts indicator scores out of sample.")
predict$position <- 2
predict$dependOn(c("endogenousIndicatorPrediction", "models", "kFolds", "repetitions", "benchmark"))
modelContainer[["predict"]] <- predict
@@ -1119,6 +1127,7 @@ checkCSemModel <- function(model, availableVars) {
#Create metrics table
metricstab <- createJaspTable(gettext("Prediction Metrics"))
+ metricstab$info <- gettext("MAE (mean absolute error), RMSE (root mean squared error), and Q\u00B2 prediction metrics for endogenous indicators. Q\u00B2 > 0 indicates that prediction error is less than using the training sample mean. When benchmarks are included, lower MAE/RMSE than the benchmark suggests the PLS-SEM model predicts better.")
if (options[["group"]] != "")
metricstab$addColumnInfo(name = "group", title = gettext("Group"), type = "string", combine = TRUE)
@@ -1136,7 +1145,7 @@ checkCSemModel <- function(model, availableVars) {
if("MAXVAR" %in% benchmarks)
metricstab$addColumnInfo(name = "maeMAXVAR", title = gettext("MAXVAR MAE"), type = "number")
- metricstab$addColumnInfo(name = "rmse", title = gettext(" Target RMSE"), type = "number")
+ metricstab$addColumnInfo(name = "rmse", title = gettext("Target RMSE"), type = "number")
if("lm" %in% benchmarks)
metricstab$addColumnInfo(name = "rmselm", title = gettext("LM RMSE"), type = "number")
@@ -1253,6 +1262,7 @@ checkCSemModel <- function(model, availableVars) {
mfm <- msc$value
# create additional fits table
fitin <- createJaspTable(gettext("Additional Fit Measures"))
+ fitin$info <- gettext("Additional model fit measures for PLS-SEM. Includes CFI, GFI, RMSEA, SRMR for the model-implied indicator correlation matrix, Goodness-of-Fit (GoF) as geometric mean of AVE and R\u00B2, and bootstrap-based distance measures (dG, dL, dML).")
fitin$addColumnInfo(name = "index", title = gettext("Index"), type = "string")
if (options[["group"]] == "")
fitin$addColumnInfo(name = "value", title = gettext("Value"), type = "number")
@@ -1346,20 +1356,21 @@ checkCSemModel <- function(model, availableVars) {
# create rsquared table
tabr2 <- createJaspTable(gettext("R-Squared"))
+ tabr2$info <- gettext("R\u00B2 and adjusted R\u00B2 for each endogenous construct. R\u00B2 represents the proportion of variance in the construct explained by its predictors in the structural model. Values of 0.75, 0.50, and 0.25 are considered substantial, moderate, and weak.")
if (options[["group"]] != "")
- tabr2$addColumnInfo(name = "grp", title = "Group", type = "string", combine = TRUE)
- tabr2$addColumnInfo(name = "var", title = "Outcome", type = "string")
+ tabr2$addColumnInfo(name = "grp", title = gettext("Group"), type = "string", combine = TRUE)
+ tabr2$addColumnInfo(name = "var", title = gettext("Outcome"), type = "string")
if (length(options[["models"]]) < 2) {
- tabr2$addColumnInfo(name = "rsq", title = "R\u00B2", type = "number")
- tabr2$addColumnInfo(name = "adjustedRsq", title = "Adjusted R\u00B2", type = "number")
+ tabr2$addColumnInfo(name = "rsq", title = gettext("R\u00B2"), type = "number")
+ tabr2$addColumnInfo(name = "adjustedRsq", title = gettext("Adjusted R\u00B2"), type = "number")
} else {
for (i in seq_along(options[["models"]])) {
tabr2$addColumnInfo(name = paste0("rsq_", i), title = options[["models"]][[i]][["name"]],
- overtitle = "R\u00B2", type = "number")
+ overtitle = gettext("R\u00B2"), type = "number")
}
for (i in seq_along(options[["models"]])) {
tabr2$addColumnInfo(name = paste0("adjustedRsq_", i), title = options[["models"]][[i]][["name"]],
- overtitle = "Adjusted R\u00B2", type = "number")
+ overtitle = gettext("Adjusted R\u00B2"), type = "number")
}
}
@@ -1497,9 +1508,10 @@ checkCSemModel <- function(model, availableVars) {
# init table
tabrho <- createJaspTable(gettext("Reliability Measures"))
+ tabrho$info <- gettext("Construct reliability measures. Cronbach's \u03B1 assumes equal indicator weights (tau-equivalence). J\u00F6reskog's \u03C1 uses the outer loadings and is the preferred measure for PLS-SEM. Dijkstra-Henseler's \u03C1_A is a consistent reliability estimate. Values above 0.70 indicate acceptable reliability.")
if (options[["group"]] != "")
- tabrho$addColumnInfo(name = "grp", title = "Group", type = "string", combine = TRUE)
- tabrho$addColumnInfo(name = "var", title = "Latent", type = "string")
+ tabrho$addColumnInfo(name = "grp", title = gettext("Group"), type = "string", combine = TRUE)
+ tabrho$addColumnInfo(name = "var", title = gettext("Latent"), type = "string")
if (length(options[["models"]]) < 2) {
tabrho$addColumnInfo(name = "rhoT", title = gettextf("Cronbach's %s", "\u03B1"), type = "number")
tabrho$addColumnInfo(name = "rhoCmm", title = gettextf("J%1$sreskog's %2$s","\u00F6", "\u03C1" ), type = "number")
@@ -1673,7 +1685,8 @@ checkCSemModel <- function(model, availableVars) {
options[["observedConstructCorrelation"]] || options[["impliedConstructCorrelation"]]) ||
!is.null(modelContainer[["cors"]])) return()
- cors <- createJaspContainer(gettext("Correlation tables"))
+ cors <- createJaspContainer(gettext("Correlation Tables"))
+ cors$info <- gettext("Observed and model-implied correlation matrices for indicators and constructs. Comparing observed and implied matrices helps assess model fit at the indicator and construct level.")
cors$position <- 3
cors$dependOn(c("observedIndicatorCorrelation",
"impliedIndicatorCorrelation",
@@ -1707,28 +1720,32 @@ checkCSemModel <- function(model, availableVars) {
# without groups, these are tables
if (options[["observedIndicatorCorrelation"]]) {
- oictab <- createJaspTable(gettext("Observed indicator correlation matrix"))
+ oictab <- createJaspTable(gettext("Observed Indicator Correlation Matrix"))
+ oictab$info <- gettext("Sample correlation matrix of the observed indicator variables.")
oictab$dependOn("observedIndicatorCorrelation")
oictab$position <- 1
corcont[["observedInd"]] <- oictab
}
if (options[["impliedIndicatorCorrelation"]]) {
- iictab <- createJaspTable(gettext("Implied indicator correlation matrix"))
+ iictab <- createJaspTable(gettext("Implied Indicator Correlation Matrix"))
+ iictab$info <- gettext("Model-implied correlation matrix of the indicator variables. Closeness to the observed matrix indicates good model fit at the indicator level.")
iictab$dependOn("impliedIndicatorCorrelation")
iictab$position <- 2
corcont[["impliedInd"]] <- iictab
}
if (options[["observedConstructCorrelation"]]) {
- occtab <- createJaspTable(gettext("Observed construct correlation matrix"))
+ occtab <- createJaspTable(gettext("Observed Construct Correlation Matrix"))
+ occtab$info <- gettext("Sample correlation matrix of the composite construct scores.")
occtab$dependOn("observedConstructCorrelation")
occtab$position <- 3
corcont[["observedCon"]] <- occtab
}
if (options[["impliedConstructCorrelation"]]) {
- icctab <- createJaspTable(gettext("Implied construct correlation matrix"))
+ icctab <- createJaspTable(gettext("Implied Construct Correlation Matrix"))
+ icctab$info <- gettext("Model-implied correlation matrix of the constructs. Closeness to the observed construct correlations indicates good structural model fit.")
icctab$dependOn("impliedConstructCorrelation")
icctab$position <- 4
corcont[["impliedCon"]] <- icctab
@@ -1739,28 +1756,32 @@ checkCSemModel <- function(model, availableVars) {
# with multiple groups these become containers
if (options[["observedIndicatorCorrelation"]]) {
- oiccont <- createJaspContainer(gettext("Observed indicator correlation matrix", initCollapsed = TRUE))
+ oiccont <- createJaspContainer(gettext("Observed Indicator Correlation Matrix"), initCollapsed = TRUE)
+ oiccont$info <- gettext("Sample correlation matrix of the observed indicator variables, shown per group.")
oiccont$dependOn("observedIndicatorCorrelation")
oiccont$position <- 1
corcont[["observedInd"]] <- oiccont
}
if (options[["impliedIndicatorCorrelation"]]) {
- iiccont <- createJaspContainer(gettext("Implied indicator correlation matrix", initCollapsed = TRUE))
+ iiccont <- createJaspContainer(gettext("Implied Indicator Correlation Matrix"), initCollapsed = TRUE)
+ iiccont$info <- gettext("Model-implied correlation matrix of the indicator variables, shown per group.")
iiccont$dependOn("impliedIndicatorCorrelation")
iiccont$position <- 2
corcont[["impliedInd"]] <- iiccont
}
if (options[["observedConstructCorrelation"]]) {
- occcont <- createJaspContainer(gettext("Observed construct correlation matrix", initCollapsed = TRUE))
+ occcont <- createJaspContainer(gettext("Observed Construct Correlation Matrix"), initCollapsed = TRUE)
+ occcont$info <- gettext("Sample correlation matrix of the composite construct scores, shown per group.")
occcont$dependOn("observedConstructCorrelation")
occcont$position <- 3
corcont[["observedCon"]] <- occcont
}
if (options[["impliedConstructCorrelation"]]) {
- icccont <- createJaspContainer(gettext("Implied construct correlation matrix", initCollapsed = TRUE))
+ icccont <- createJaspContainer(gettext("Implied Construct Correlation Matrix"), initCollapsed = TRUE)
+ icccont$info <- gettext("Model-implied correlation matrix of the constructs, shown per group.")
icccont$dependOn("impliedConstructCorrelation")
icccont$position <- 4
corcont[["impliedCon"]] <- icccont
diff --git a/R/sem.R b/R/sem.R
index 6317bebc..4e2c993d 100644
--- a/R/sem.R
+++ b/R/sem.R
@@ -660,7 +660,8 @@ checkLavaanModel <- function(model, availableVars) {
if (!is.null(modelContainer[["fittab"]])) return()
- fittab <- createJaspTable(title = gettext("Model fit"))
+ fittab <- createJaspTable(title = gettext("Model Fit"))
+ fittab$info <- gettext("Model fit statistics including AIC, BIC, number of parameters, and a chi-square test for exact fit. A non-significant chi-square suggests the model fits the data well, though this test is sensitive to sample size.")
fittab$dependOn(c("models", "warnings"))
fittab$position <- 0
@@ -911,6 +912,7 @@ checkLavaanModel <- function(model, availableVars) {
if (modelContainer$getError()) return()
params <- createJaspContainer(gettext("Parameter Estimates"))
+ params$info <- gettext("Parameter estimates from the structural equation model, organized by type: factor loadings, regression coefficients, variances, covariances, and additional parameters.")
params$position <- 1
params$dependOn(c("ciLevel", "bootstrapCiType", "standardizedEstimate", "models", "standardizedEstimateType"))
@@ -940,6 +942,7 @@ checkLavaanModel <- function(model, availableVars) {
# Measurement model
indtab <- createJaspTable(title = gettext("Factor Loadings"))
+ indtab$info <- gettext("Factor loadings from the measurement model (=~ operator). Each loading reflects how strongly a latent variable is related to its observed indicator. The first indicator loading is typically fixed to 1 to set the scale of the latent variable.")
if (options[["group"]] != "")
indtab$addColumnInfo(name = "group", title = gettext("Group"), type = "string", combine = TRUE)
@@ -948,7 +951,7 @@ checkLavaanModel <- function(model, availableVars) {
indtab$addColumnInfo(name = "rhs", title = gettext("Indicator"), type = "string")
indtab$addColumnInfo(name = "label", title = "", type = "string")
indtab$addColumnInfo(name = "est", title = estTitle, type = "number")
- indtab$addColumnInfo(name = "se", title = gettext("Std. error"), type = "number")
+ indtab$addColumnInfo(name = "se", title = gettext("Std. Error"), type = "number")
indtab$addColumnInfo(name = "z", title = gettext("z-value"), type = "number")
indtab$addColumnInfo(name = "pvalue", title = gettext("p"), type = "pvalue")
indtab$addColumnInfo(name = "ci.lower", title = gettext("Lower"), type = "number",
@@ -959,7 +962,8 @@ checkLavaanModel <- function(model, availableVars) {
pecont[["ind"]] <- indtab
# Structural Model
- regtab <- createJaspTable(title = gettext("Regression coefficients"))
+ regtab <- createJaspTable(title = gettext("Regression Coefficients"))
+ regtab$info <- gettext("Regression coefficients from the structural part of the model (~ operator). These represent directed effects of predictors on outcomes among latent and/or observed variables.")
if (options[["group"]] != "")
regtab$addColumnInfo(name = "group", title = gettext("Group"), type = "string", combine = TRUE)
@@ -980,7 +984,8 @@ checkLavaanModel <- function(model, availableVars) {
# Latent variances
- lvartab <- createJaspTable(title = gettext("Factor variances"))
+ lvartab <- createJaspTable(title = gettext("Factor Variances"))
+ lvartab$info <- gettext("Estimated variances of the latent variables. For exogenous latent variables these are total variances; for endogenous latent variables these are residual variances (the variance not explained by predictors).")
if (options[["group"]] != "")
lvartab$addColumnInfo(name = "group", title = gettext("Group"), type = "string", combine = TRUE)
@@ -999,7 +1004,8 @@ checkLavaanModel <- function(model, availableVars) {
pecont[["lvar"]] <- lvartab
# Latent covariances
- lcovtab <- createJaspTable(title = gettext("Factor covariances"))
+ lcovtab <- createJaspTable(title = gettext("Factor Covariances"))
+ lcovtab$info <- gettext("Estimated covariances between latent variables (~~ operator). These represent undirected associations between latent variables.")
if (options[["group"]] != "")
lcovtab$addColumnInfo(name = "group", title = gettext("Group"), type = "string", combine = TRUE)
@@ -1018,7 +1024,8 @@ checkLavaanModel <- function(model, availableVars) {
pecont[["lcov"]] <- lcovtab
# Residual variances
- vartab <- createJaspTable(title = gettext("Residual variances"))
+ vartab <- createJaspTable(title = gettext("Residual Variances"))
+ vartab$info <- gettext("Residual variances of the observed variables: the variance not explained by the latent variables. Negative residual variances (Heywood cases) may indicate model misspecification.")
if (options[["group"]] != "")
vartab$addColumnInfo(name = "group", title = gettext("Group"), type = "string", combine = TRUE)
@@ -1037,7 +1044,8 @@ checkLavaanModel <- function(model, availableVars) {
pecont[["var"]] <- vartab
# Residual covariances
- covtab <- createJaspTable(title = gettext("Residual covariances"))
+ covtab <- createJaspTable(title = gettext("Residual Covariances"))
+ covtab$info <- gettext("Residual covariances between observed variables (~~ operator). These represent correlated errors, i.e., shared variance between indicators not accounted for by the latent variables.")
if (options[["group"]] != "")
covtab$addColumnInfo(name = "group", title = gettext("Group"), type = "string", combine = TRUE)
@@ -1061,6 +1069,7 @@ checkLavaanModel <- function(model, availableVars) {
if (fit@Options$meanstructure) {
mutab <- createJaspTable(title = gettext("Intercepts"))
+ mutab$info <- gettext("Intercept (mean) parameters for observed and latent variables in the mean structure. For observed variables, these are the expected values when all predictors are zero.")
allTables[[length(allTables) + 1]] <- mutab
if (options[["group"]] != "")
@@ -1087,6 +1096,7 @@ checkLavaanModel <- function(model, availableVars) {
# thresholds
if (fit@Options$categorical) {
thrtab <- createJaspTable(title = gettext("Thresholds"))
+ thrtab$info <- gettext("Threshold parameters for ordinal observed variables. These define the cut-points on the underlying continuous distribution that separate the observed categories.")
if (options[["group"]] != "")
thrtab$addColumnInfo(name = "group", title = gettext("Group"), type = "string", combine = TRUE)
@@ -1107,7 +1117,8 @@ checkLavaanModel <- function(model, availableVars) {
originalSyntaxTable <- modelContainer[["originalSyntax"]][["object"]][[1]]
if (nrow(originalSyntaxTable[originalSyntaxTable$op == ":=",]) > 0) {
- deftab <- createJaspTable(title = gettext("Defined parameters"))
+ deftab <- createJaspTable(title = gettext("Defined Parameters"))
+ deftab$info <- gettext("User-defined parameters specified with the := operator. These are functions of existing model parameters, such as indirect effects or sums of coefficients. Standard errors are computed using the Delta method.")
allTables[[length(allTables) + 1]] <- deftab
deftab$addColumnInfo(name = "lhs", title = gettext("Name"), type = "string")
@@ -1122,7 +1133,8 @@ checkLavaanModel <- function(model, availableVars) {
pecont[["def"]] <- deftab
} else {
- indefftab <- createJaspTable(title = gettext("Indirect effects"))
+ indefftab <- createJaspTable(title = gettext("Indirect Effects"))
+ indefftab$info <- gettext("Indirect effects of predictors on outcomes transmitted through mediating variables. These are computed as the product of the path coefficients along the indirect pathway.")
allTables[[length(allTables) + 1]] <- indefftab
if (options[["group"]] != "")
@@ -1140,7 +1152,8 @@ checkLavaanModel <- function(model, availableVars) {
pecont[["indeff"]] <- indefftab
- totefftab <- createJaspTable(title = gettext("Total effects"))
+ totefftab <- createJaspTable(title = gettext("Total Effects"))
+ totefftab$info <- gettext("Total effects combining direct and all indirect effects of predictors on outcomes.")
allTables[[length(allTables) + 1]] <- totefftab
if (options[["group"]] != "")
@@ -1447,12 +1460,14 @@ checkLavaanModel <- function(model, availableVars) {
if (!ready || modelContainer$getError()) return()
fitContainer <- createJaspContainer(gettext("Additional Fit Measures"))
+ fitContainer$info <- gettext("Additional model fit indices and information criteria for evaluating overall model quality.")
fitContainer$dependOn(c("additionalFitMeasures", "models"))
fitContainer$position <- 0.5
modelContainer[["addfit"]] <- fitContainer
# Fit indices
- fitinds <- createJaspTable(gettext("Fit indices"))
+ fitinds <- createJaspTable(gettext("Fit Indices"))
+ fitinds$info <- gettext("Model fit indices including incremental indices (CFI, TLI, NFI), absolute indices (RMSEA, SRMR, GFI), and information criteria (AIC, BIC). Common guidelines: CFI/TLI > .95, RMSEA < .06, SRMR < .08 indicate good fit, though these should be interpreted cautiously.")
fitContainer[["fitMeasures"]] <- fitinds
fitinds$addColumnInfo(name = "index", title = gettext("Index"), type = "string")
@@ -1531,7 +1546,8 @@ checkLavaanModel <- function(model, availableVars) {
fitinds$addFootnote(fnote)
# a table only with the T-size stuff
- ftsize <- createJaspTable(gettext("T-size fit indices"))
+ ftsize <- createJaspTable(gettext("T-Size Fit Indices"))
+ ftsize$info <- gettext("T-size equivalence testing fit indices (Marcoulides & Yuan, 2017). These provide data-driven cutoff values for CFI and RMSEA that replace conventional rules of thumb. The poor-fair and fair-close limits define ranges for interpreting fit.")
ftsize$addCitation("Katerina M. Marcoulides & Ke-Hai Yuan (2017) New Ways to Evaluate Goodness of Fit: A Note on Using Equivalence Testing to Assess Structural Equation Models. *Structural Equation Modeling: A Multidisciplinary Journal, 24*(1), 148-153, https://doi.org/10.1080/10705511.2016.1225260")
fitContainer[["fitTSize"]] <- ftsize
@@ -1577,6 +1593,7 @@ checkLavaanModel <- function(model, availableVars) {
# init table
tabr2 <- createJaspTable(gettext("R-Squared"))
+ tabr2$info <- gettext("Proportion of variance in each endogenous variable explained by its predictors in the model. Values range from 0 to 1, with higher values indicating more variance explained.")
if (options[["group"]] != "")
tabr2$addColumnInfo(name = "__grp__", title = "", type = "string", combine = TRUE)
tabr2$addColumnInfo(name = "__var__", title = "", type = "string")
@@ -1685,7 +1702,8 @@ checkLavaanModel <- function(model, availableVars) {
if (!options[["ave"]] || !is.null(modelContainer[["AVE"]])) return()
# init table
- avetab <- createJaspTable(gettext("Average variance extracted"))
+ avetab <- createJaspTable(gettext("Average Variance Extracted"))
+ avetab$info <- gettext("Average Variance Extracted (AVE) measures the amount of variance captured by a latent construct relative to measurement error. AVE values above 0.5 indicate adequate convergent validity, meaning the construct explains more than half the variance of its indicators.")
if (options[["group"]] != "")
avetab$addColumnInfo(name = "group", title = gettext("Group"), type = "string", combine = TRUE)
avetab$addColumnInfo(name = "factor", title = gettext("Latent"), type = "string")
@@ -1779,6 +1797,7 @@ checkLavaanModel <- function(model, availableVars) {
# init table
reliabilitytab <- createJaspTable(gettext("Reliability"))
+ reliabilitytab$info <- gettext("Composite reliability coefficients for each latent construct. Coefficient \u03b1 (alpha) assumes tau-equivalence (equal loadings), while coefficient \u03c9 (omega) allows for congeneric indicators (unequal loadings) and is generally preferred. Values above 0.7 are commonly considered acceptable.")
if (options[["group"]] != "")
reliabilitytab$addColumnInfo(name = "group", title = gettext("Group"), type = "string", combine = TRUE)
reliabilitytab$addColumnInfo(name = "factor", title = "", type = "string")
@@ -1944,13 +1963,14 @@ checkLavaanModel <- function(model, availableVars) {
.semHtmtTables <- function(fit, model, parentContainer, options, ready, dataset) {
if (is.null(model)) {
htmtcont <- parentContainer
- title <- gettext("Heterotrait-monotrait ratio")
+ title <- gettext("Heterotrait-Monotrait Ratio")
} else {
htmtcont <- createJaspContainer(model[["name"]], initCollapsed = TRUE)
title <- ""
}
htmttab <- createJaspTable(title = title)
+ htmttab$info <- gettext("Heterotrait-Monotrait (HTMT) ratio of correlations for assessing discriminant validity. HTMT values below 0.85 (conservative) or 0.90 (liberal) suggest that constructs are empirically distinct from each other.")
htmtcont[["htmttab"]] <- htmttab
if (options[["group"]] == "") {
@@ -2013,7 +2033,8 @@ checkLavaanModel <- function(model, availableVars) {
.semMardiasCoefficient <- function(modelContainer, dataset, options, ready) {
if (!options[["mardiasCoefficient"]] || !is.null(modelContainer[["semMardiasTable"]])) return()
- mardiatab <- createJaspTable(title = gettext("Mardia's coefficients"))
+ mardiatab <- createJaspTable(title = gettext("Mardia's Coefficients"))
+ mardiatab$info <- gettext("Mardia's multivariate skewness and kurtosis coefficients for assessing whether the data meet the multivariate normality assumption. Significant values suggest non-normality, which may affect chi-square tests and standard errors under ML estimation.")
mardiatab$position <- .2
mardiatab$addColumnInfo(name = "Type", title = "", type = "string")
@@ -2076,7 +2097,8 @@ checkLavaanModel <- function(model, availableVars) {
if (!(options[["observedCovariance"]] || options[["impliedCovariance"]] ||
options[["residualCovariance"]] || options[["standardizedResidual"]]) || !is.null(modelContainer[["covars"]])) return()
- covars <- createJaspContainer(gettext("Covariance tables"))
+ covars <- createJaspContainer(gettext("Covariance Tables"))
+ covars$info <- gettext("Observed, model-implied, and residual covariance matrices. Comparing these matrices helps evaluate local model fit.")
covars$position <- 3
covars$dependOn(c("observedCovariance", "impliedCovariance", "residualCovariance",
"standardizedResidual", "models"))
@@ -2107,28 +2129,32 @@ checkLavaanModel <- function(model, availableVars) {
# without groups, these are tables
if (options[["observedCovariance"]]) {
- octab <- createJaspTable("Observed covariance matrix")
+ octab <- createJaspTable(gettext("Observed Covariance Matrix"))
+ octab$info <- gettext("Sample covariance matrix of the observed variables used for model estimation.")
octab$dependOn("observedCovariance")
octab$position <- 1
cocont[["observed"]] <- octab
}
if (options[["impliedCovariance"]]) {
- ictab <- createJaspTable("Implied covariance matrix")
+ ictab <- createJaspTable(gettext("Implied Covariance Matrix"))
+ ictab$info <- gettext("Model-implied covariance matrix derived from the estimated parameters. Close correspondence with the observed covariance matrix indicates good model fit.")
ictab$dependOn("impliedCovariance")
ictab$position <- 2
cocont[["implied"]] <- ictab
}
if (options[["residualCovariance"]]) {
- rctab <- createJaspTable("Residuals covariance matrix")
+ rctab <- createJaspTable(gettext("Residual Covariance Matrix"))
+ rctab$info <- gettext("Difference between the observed and model-implied covariance matrices. Small residuals indicate that the model reproduces the observed covariances well.")
rctab$dependOn("residualCovariance")
rctab$position <- 3
cocont[["residual"]] <- rctab
}
if (options[["standardizedResidual"]]) {
- srtab <- createJaspTable("Standardized residuals covariance matrix")
+ srtab <- createJaspTable(gettext("Standardized Residual Covariance Matrix"))
+ srtab$info <- gettext("Standardized residual covariances. Values exceeding |2| may indicate localized areas of poor fit for specific pairs of variables.")
srtab$dependOn("standardizedResidual")
srtab$position <- 4
cocont[["stdres"]] <- srtab
@@ -2139,28 +2165,32 @@ checkLavaanModel <- function(model, availableVars) {
# with multiple groups these become containers
if (options[["observedCovariance"]]) {
- occont <- createJaspContainer("Observed covariance matrix", initCollapsed = TRUE)
+ occont <- createJaspContainer(gettext("Observed Covariance Matrix"), initCollapsed = TRUE)
+ occont$info <- gettext("Sample covariance matrix of the observed variables used for model estimation.")
occont$dependOn("observedCovariance")
occont$position <- 1
cocont[["observed"]] <- occont
}
if (options[["impliedCovariance"]]) {
- iccont <- createJaspContainer("Implied covariance matrix", initCollapsed = TRUE)
+ iccont <- createJaspContainer(gettext("Implied Covariance Matrix"), initCollapsed = TRUE)
+ iccont$info <- gettext("Model-implied covariance matrix derived from the estimated parameters. Close correspondence with the observed covariance matrix indicates good model fit.")
iccont$dependOn("impliedCovariance")
iccont$position <- 2
cocont[["implied"]] <- iccont
}
if (options[["residualCovariance"]]) {
- rccont <- createJaspContainer("Residuals covariance matrix", initCollapsed = TRUE)
+ rccont <- createJaspContainer(gettext("Residual Covariance Matrix"), initCollapsed = TRUE)
+ rccont$info <- gettext("Difference between the observed and model-implied covariance matrices. Small residuals indicate that the model reproduces the observed covariances well.")
rccont$dependOn("residualCovariance")
rccont$position <- 3
cocont[["residual"]] <- rccont
}
if (options[["standardizedResidual"]]) {
- srcont <- createJaspContainer("Standardized residuals covariance matrix", initCollapsed = TRUE)
+ srcont <- createJaspContainer(gettext("Standardized Residual Covariance Matrix"), initCollapsed = TRUE)
+ srcont$info <- gettext("Standardized residual covariances. Values exceeding |2| may indicate localized areas of poor fit for specific pairs of variables.")
srcont$dependOn("standardizedResidual")
srcont$position <- 4
cocont[["stdres"]] <- srcont
@@ -2338,7 +2368,8 @@ checkLavaanModel <- function(model, availableVars) {
.semMI <- function(modelContainer, dataset, options, ready) {
if (!options[["modificationIndex"]] || !is.null(modelContainer[["modindices"]])) return()
- modindices <- createJaspContainer(gettext("Modification indices"))
+ modindices <- createJaspContainer(gettext("Modification Indices"))
+ modindices$info <- gettext("Modification indices (MI) estimate the expected decrease in the model chi-square statistic if a currently fixed parameter were freed. The expected parameter change (EPC) indicates the approximate value of the freed parameter.")
modindices$position <- 4
modindices$dependOn(c("modificationIndex", "modificationIndexHiddenLow", "modificationIndexThreshold", "models"))
@@ -2364,17 +2395,18 @@ checkLavaanModel <- function(model, availableVars) {
}
semModIndicesTable <- createJaspTable(title = gettext("Modification Indices"))
+ semModIndicesTable$info <- gettext("MI is the expected chi-square decrease if a fixed parameter is freed. EPC is the expected parameter change. SEPC columns show standardized versions (lv = latent only, all = fully, nox = excluding exogenous observed).")
semModIndicesTable$addColumnInfo(name = "lhs", title = "", type = "string")
semModIndicesTable$addColumnInfo(name = "op", title = "", type = "string")
semModIndicesTable$addColumnInfo(name = "rhs", title = "", type = "string")
if (options[["group"]] != "")
- semModIndicesTable$addColumnInfo(name = "group", title = gettext("group"), type = "string")
- semModIndicesTable$addColumnInfo(name = "mi", title = gettext("mi"), type = "number")
- semModIndicesTable$addColumnInfo(name = "epc", title = gettext("epc"), type = "number")
- semModIndicesTable$addColumnInfo(name = "sepc.lv", title = gettext("sepc (lv)"), type = "number")
- semModIndicesTable$addColumnInfo(name = "sepc.all", title = gettext("sepc (all)"), type = "number")
- semModIndicesTable$addColumnInfo(name = "sepc.nox", title = gettext("sepc (nox)"), type = "number")
+ semModIndicesTable$addColumnInfo(name = "group", title = gettext("Group"), type = "string")
+ semModIndicesTable$addColumnInfo(name = "mi", title = gettext("MI"), type = "number")
+ semModIndicesTable$addColumnInfo(name = "epc", title = gettext("EPC"), type = "number")
+ semModIndicesTable$addColumnInfo(name = "sepc.lv", title = gettext("SEPC (lv)"), type = "number")
+ semModIndicesTable$addColumnInfo(name = "sepc.all", title = gettext("SEPC (all)"), type = "number")
+ semModIndicesTable$addColumnInfo(name = "sepc.nox", title = gettext("SEPC (nox)"), type = "number")
semModIndicesTable$showSpecifiedColumnsOnly <- TRUE
@@ -2412,7 +2444,8 @@ checkLavaanModel <- function(model, availableVars) {
.semSensitivity <- function(modelContainer, dataset, options, ready) {
if (!options[["sensitivityAnalysis"]] || !is.null(modelContainer[["sensitivity"]])) return()
- sensitivity <- createJaspContainer(gettext("Sensitivity analysis"))
+ sensitivity <- createJaspContainer(gettext("Sensitivity Analysis"))
+ sensitivity$info <- gettext("Sensitivity analysis using phantom variables to assess the robustness of path estimates to unmeasured confounding. Evaluates whether conclusions change when an unobserved common cause is introduced.")
sensitivity$position <- 4.1
sensitivity$dependOn(c("sensitivityAnalysis", "searchAlgorithm", "optimizerFunction", "sizeOfSolutionArchive", "numberOfAnts", "alpha", "maxIterations", "setSeed", "seed", "models"))
@@ -2439,7 +2472,8 @@ checkLavaanModel <- function(model, availableVars) {
# Summary of sensitivity analysis
- sensumtab <- createJaspTable(title = gettext("Summary of sensitivity analysis"))
+ sensumtab <- createJaspTable(title = gettext("Summary of Sensitivity Analysis"))
+ sensumtab$info <- gettext("Summary of how path estimates and their significance change when phantom variables representing unmeasured confounders are introduced. P* denotes the p-value from the sensitivity model.")
if (options[["group"]] != "")
sensumtab$addColumnInfo(name = "group", title = gettext("Group"), type = "string", combine = TRUE)
@@ -2592,7 +2626,8 @@ checkLavaanModel <- function(model, availableVars) {
# Sensitivity parameters that led to a change in significance
- senpartab <- createJaspTable(title = gettext("Sensitivity parameters that led to a change in significance"))
+ senpartab <- createJaspTable(title = gettext("Sensitivity Parameters That Led to a Change in Significance"))
+ senpartab$info <- gettext("Phantom variable coefficients from sensitivity models where the statistical significance of a path changed compared to the original model.")
if (options[["group"]] != "")
senpartab$addColumnInfo(name = "group", title = gettext("Group"), type = "string", combine = TRUE)
@@ -2670,7 +2705,8 @@ checkLavaanModel <- function(model, availableVars) {
# }
# Summary of sensitivity parameters
- sensumpartab <- createJaspTable(title = gettext("Summary of sensitivity parameters"))
+ sensumpartab <- createJaspTable(title = gettext("Summary of Sensitivity Parameters"))
+ sensumpartab$info <- gettext("Summary statistics (mean, min, max) of the phantom variable coefficients across all sensitivity analyses, indicating the range of unmeasured confounding explored.")
if (options[["group"]] != "")
sensumpartab$addColumnInfo(name = "group", title = gettext("Group"), type = "string", combine = TRUE)
@@ -2700,7 +2736,8 @@ checkLavaanModel <- function(model, availableVars) {
.semPathPlot <- function(modelContainer, dataset, options, ready) {
if (!options[["pathPlot"]] || !ready || !is.null(modelContainer[["plot"]])) return()
- pcont <- createJaspContainer(gettext("Path diagram"))
+ pcont <- createJaspContainer(gettext("Path Diagram"))
+ pcont$info <- gettext("Graphical representation of the model showing latent variables (circles), observed variables (squares), and the paths between them.")
pcont$position <- 7
pcont$dependOn(c("pathPlot", "pathPlotParameter", "pathPlotLegend", "models", "pathPlotParameterStandardized"))
@@ -2721,7 +2758,7 @@ checkLavaanModel <- function(model, availableVars) {
.semCreatePathPlot <- function(fit, modelname, parentContainer, options, ready) {
if (is.null(modelname)) {
- modelname <- gettext("Path diagram")
+ modelname <- gettext("Path Diagram")
}
if (options[["group"]] == "") {
diff --git a/inst/Description.qml b/inst/Description.qml
index 72687f7a..aafd1387 100644
--- a/inst/Description.qml
+++ b/inst/Description.qml
@@ -6,7 +6,7 @@ Description
title : qsTr("SEM")
description: qsTr("Evaluate latent data structures with Yves Rosseel’s lavaan program")
icon: "sem-latreg.svg"
- preloadData: false
+ preloadData: true
hasWrappers: true
Analysis
@@ -21,7 +21,6 @@ Description
title: qsTr("Partial Least Squares SEM")
qml: "PLSSEM.qml"
func: "PLSSEM"
- preloadData: true
}
Analysis
@@ -50,6 +49,5 @@ Description
title: qsTr("MNLFA")
qml: "ModeratedNonLinearFactorAnalysis.qml"
func: "ModeratedNonLinearFactorAnalysis"
- preloadData: true
}
}
diff --git a/inst/help/MIMIC.md b/inst/help/MIMIC.md
deleted file mode 100644
index 060abaa3..00000000
--- a/inst/help/MIMIC.md
+++ /dev/null
@@ -1,51 +0,0 @@
-MIMIC models
-============
-
-Multiple-Indicators-multiple-causes (MIMIC) models with a single latent variable. It can be used to study the effects of covariates (causes) on a latent variable. MIMIC analysis in JASP is based on the excellent `lavaan` software (Rosseel, 2012). More information about `lavaan` can be found here: [lavaan.org](http://lavaan.org).
-
-MIMIC in JASP allows for continuous and ordinal endogenous variables and binary and continuous exogenous variables. For binary endogenous variables, recode your variable into a dummy continous variable with 0 for the first category and 1 for the second category. The linearity assumption still holds, however, i.e., SEM does not perform logistic regression.
-
-For more information on allowed data types, see [the lavaan website](http://lavaan.ugent.be/tutorial/cat.html).
-
-## Input
-#### Indicators
-These are the indicators, together defining the latent outcome. A minimum of 3 scale or ordinal variables are required for the analysis to run.
-
-#### Predictors
-These are the causes of the latent outcome. One or multiple predictor variable(s). A minimum of one predictor is required for MIMIC models. Otherwise, see Confirmatory Factor Analysis.
-
-### Options
-#### Standardized estimates
-Check this to show three types of standardized estimates: where all variables are standardized, where the latent variables are standardized, and where the endogenous variables are standardized. See `lavaan` for more information.
-
-#### Show lavaan syntax
-Show the syntax needed to estimate this model using `lavaan` in `R` or the `SEM` module in `JASP`.
-
-#### R-Squared
-A table with the proportion of variance explained for each of the endogenous variables in the MIMIC model (the indicators).
-
-#### Additional fit measures
-Check this to display several different fit measures for this model, such as RMSEA, CFI, and other information criteria.
-
-#### Confidence intervals
-Here, you can select different ways of estimating the uncertainty around the parameter estimates, as well as the width of the confidence intervals.
-
-### Plots
-
-#### Path plot
-This option allows users to graphically display the path model being estimated by the MIMIC analysis. Optionally, the parameters can be shown in this plot. If the labels overlap, the plot can be saved as an EPS and edited in any vector editing program.
-
-### Advanced
-#### Missing value handling
-How missing values are handled. By default, this is set to full information maximum likelihood (FIML), which automatically computes the estimates using all the available information -- assuming missing at random (MAR) missingness patterns. A suboptimal alternative is available in listwise deletion.
-
-#### Emulation
-Emulate the output from different SEM programs. Default none.
-
-#### Estimator
-Different choices for estimators can be found here. We suggest leaving this at `auto` for most -- if not all -- purposes.
-
-References
-==========
-
-- Rosseel, Y. (2012). Lavaan: An R package for structural equation modeling and more. Version 0.5–12 (BETA). Journal of Statistical Software, 48(2), 1-36.
diff --git a/inst/help/MediationAnalysis.md b/inst/help/MediationAnalysis.md
deleted file mode 100644
index 77c78fd2..00000000
--- a/inst/help/MediationAnalysis.md
+++ /dev/null
@@ -1,59 +0,0 @@
-Mediation analysis
-============
-
-Mediation analysis with potentially multiple predictors, multiple mediators, multiple outcomes, and optional correction for multiple background confounders. Mediation analysis in JASP is based on the excellent `lavaan` software (Rosseel, 2012). More information about `lavaan` can be found here: [lavaan.org](http://lavaan.org).
-
-
-Mediation analysis in JASP allows for continuous and ordinal endogenous variables and binary and continuous exogenous variables. For binary endogenous variables, recode your variable into a dummy continous variable with 0 for the first category and 1 for the second category. The linearity assumption still holds, however, i.e., SEM does not perform logistic regression.
-
-For more information on allowed data types, see [the lavaan website](http://lavaan.ugent.be/tutorial/cat.html).
-
-### Details about testing indirect effects
-Testing whether an indirect effect exists is best done via the "Bootstrap" option under `Options > Confidence Intervals > Methods > Bootstrap`. The confidence intervals are then computed using the bias-corrected percentile method as suggested by Biesanz, Falk, and Savalei (2010).
-
-
-## Input
-#### Predictors
-One or multiple predictor variable(s), predicting the mediator(s) and the outcome variable(s).
-
-#### Mediators
-The variable(s) through which the indirect effect of the predictor(s) on the outcome variable(s) is hypothesized to flow.
-
-#### Outcome
-The variable(s) predicted by the predictor(s) and the mediator(s).
-
-#### Background confounders
-Variables explaining the predictor(s), mediator(s), and outcome variable(s): the direct, indirect, and total effects are estimated conditional on these variables.
-
-#### Standardized estimates
-Check this to standardize (mean = 0, sd = 1) all variables before estimation.
-
-#### Show lavaan syntax
-Show the syntax needed to estimate this model using `lavaan` in `R` or the `SEM` module in `JASP`.
-
-#### Show R-Squared
-A table with the proportion of variance explained for each of the endogenous variables in the mediation model.
-
-#### Parameter estimates
-Under this option, you can check and uncheck different parameter estimates tables to display in the main output of the mediation analysis.
-
-#### Confidence intervals
-Here, you can select different ways of estimating the uncertainty around the parameter estimates. A note under each of the main tables will display the methods by which standard errors and confidence intervals are computed. See also the __details about testing indirect effects__ section above.
-
-#### Plots
-This option allows users to graphically display the path model being estimated by the mediation analysis. Optionally, the parameters can be shown in this plot. If the labels overlap, the plot can be saved as an EPS and edited in any vector editing program.
-
-#### Emulation
-Emulate the output from different SEM programs. Default none.
-
-#### Missing value handling
-How missing values are handled. By default, this is set to full information maximum likelihood (FIML), which automatically computes the estimates using all the available information -- assuming missing at random (MAR) missingness patterns. A suboptimal alternative is available in listwise deletion.
-
-#### Estimator
-Different choices for estimators can be found here. We suggest leaving this at `auto` for most -- if not all -- purposes.
-
-References
-==========
-
-- Jeremy C. Biesanz, Carl F. Falk & Victoria Savalei (2010) Assessing Mediational Models: Testing and Interval Estimation for Indirect Effects, Multivariate Behavioral Research, 45:4, 661-701, DOI: 10.1080/00273171.2010.498292
-- Rosseel, Y. (2012). Lavaan: An R package for structural equation modeling and more. Version 0.5–12 (BETA). Journal of Statistical Software, 48(2), 1-36.
diff --git a/inst/help/MediationAnalysis_nl.md b/inst/help/MediationAnalysis_nl.md
deleted file mode 100644
index 1c3aecea..00000000
--- a/inst/help/MediationAnalysis_nl.md
+++ /dev/null
@@ -1,59 +0,0 @@
-Mediatie Analyse
-============
-
-Mediatie analyse met mogelijk meerdere predictoren, meerdere mediatoren, meerdere uitkomsten, en een optionele correctie voor meerdere achtergrond verstoringsvariabelen. Mediatie analyse in JASP is gebaseerd op de uitstekende `lavaan` software (Rosseel, 2012). Er is meer informatie te vinden over `lavaan` op [lavaan.org](http://lavaan.org).
-
-Mediatie analyse in JASP is mogelijk voor continue en ordinale variabelen en voor binaire en continue exogene variabelen. Voor binaire endogene variabelen kunt u uw variabelen hercoderen in een "dummy" continue variabele met 0 als de eerste categorie en 1 voor de tweede. De lineariteitsassumptie geldt nog steeds, maar SEM doet bijvoorbeeld geen logistische regressies.
-
-
-Voor meer informatie over de toegestane datatypen, zie [de lavaan website](http://lavaan.ugent.be/tutorial/cat.html).
-
-### Details over het toetsen van indirecte effecten
-Toetsen of een indirect effect bestaat kan het beste worden gedaan met de "Bootstrap" optie onder `Opties > betrouwbaarheidsintervallen > Methoden > Bootstrap`. De betrouwbaarheidsintervallen worden dan berekend met de voor bias gecorrigeerde percentielmethode zoals besproken in Biesanz, Falk, and Savalei (2010).
-
-
-## In
-#### Predictoren
-Een of meerdere predictor variabele(n) die de mediator(en) en de uitkomst variabele(n) voorspellen.
-
-#### Mediatoren
-De variabele waardoor het indirecte effect van de predictor(en) op de uitkomst variabele(n) wordt verondersteld te stromen.
-
-#### Uitkomst
-De variabele(n) die wordt(worden) voorspeld door de predictor(en) en de mediator(en).
-
-#### Achtergrond verstoringsvariabelen
-Variabelen die variantie in de predictor(en), mediator(en) en uitkomst variabele(n) verklaren: de directe, indirecte en totale effecten worden geconditioneerd op deze variabelen.
-
-#### Gestandaardiseerde schattingen
-Vink dit aan om alle variabelen te standaardiseren voor de schatting (gemiddelde = 0, sd = 1).
-
-#### Toon lavaan syntax
-Laat de syntax zien die nodig is om dit model te schatten met `lavaan` in `R` of met de `SEM` module in `JASP`.
-
-#### Laat R-Kwadraat zien
-Een tabel met de proportie van de variantie die wordt verklaard voor elk van de endogene variabelen in het mediatie model.
-
-#### Parameterschattingen
-Onder deze optie kunt u verschillende parameterschattings-tabellen aanvinken om weer te geven in de uitvoer van de analyse.
-
-#### Betrouwbaarheidsintervallen
-Hier kunt u verschillende manieren om de onzekerheid rond de parameterschattingen schatten. Een voetnoot onder de hoofdtabellen zal de methode weergeven waarmee de standaardafwijking en betrouwbaarheidsintervallen zijn berekend. Zie ook de __details over het testen van indirecte effecten__
-
-#### Grafieken
-Deze optie laat gebruikers het padmodel dat is geschat door de mediatie analyse grafisch weergeven. De parameters kunnen worden weergegeven in deze grafiek. Als de labels overlappen kan de grafiek worden opgeslagen als een EPS en worden bewerkt in een vector bewerkingsprogramma.
-
-#### Emulatie
-Emuleer de uitvoer van verschillende SEM programma's. Geen standaardoptie.
-
-#### Omgaan met ontbrekende waarden
-Hoe met ontbrekende waarden wordt omgegaan. De standaardinstelling is volle informatie maximum likelihood (FIML), welke automatisch de schattingen berekent met alle beschikbare informatie -- dit neemt aan dat er wordt gemist bij aselecte (MAR) missingness patterns. Een suboptimaal alternatief is beschikbaar in lijstgewijze verwijdering.
-
-#### Schatter
-Verschillende keuzes voor schatters zijn beschikbaar. Wij raden aan om dit te laten staan op `auto` voor de meeste (zo niet alle) doeleinden.
-
-Referenties
-==========
-
-- Jeremy C. Biesanz, Carl F. Falk & Victoria Savalei (2010) Assessing Mediational Models: Testing and Interval Estimation for Indirect Effects, Multivariate Behavioral Research, 45:4, 661-701, DOI: 10.1080/00273171.2010.498292
-- Rosseel, Y. (2012). Lavaan: An R package for structural equation modeling and more. Version 0.5–12 (BETA). Journal of Statistical Software, 48(2), 1-36.
diff --git a/inst/help/PLSSEM.md b/inst/help/PLSSEM.md
deleted file mode 100644
index 53f0d4aa..00000000
--- a/inst/help/PLSSEM.md
+++ /dev/null
@@ -1,157 +0,0 @@
-# Partial Least Squares Structural Equation Modeling (PLS-SEM) in JASP
-
-This document explains how to perform Partial Least Squares Structural Equation Modeling (PLS-SEM) in JASP using the various options provided in the user interface.
-
-## 1. Model Setup
----
-In the **Model** section, you can specify the structural equation model using lavaan syntax.
-The following operators can be used: =~ to specify a latent variable
-measured by a set of indicators; <~ to specify a composite/emergent variable that is made up of a set of indicators;
-and ~ to specify the structural model, i.e., the relationships
-between the latent variables and the composites. In specifying
-the relationships between the latent variables and the composites,
-they must not be isolated in the structural model. In addition,
-no indicator may be connected to more than one latent variable/composite.
-Furthermore, the structural model may not include any observed variables, i.e.,
-to include observed variables in the structural model they must be specified as
-a single-indicator construct. Finally, a grouping variable can be selected.
-In this case, the model is estimated separately for each group.
-
-- **Grouping Variable**: You can select the grouping variable for multi-group analysis.
-The grouping variable is optional and can be left empty if not required.
-
-## 2. Estimation Options
----
-In the **Estimation** section, the following options are available:
-
-- **Consistent partial least squares**: Enables the option to use consistent partial least squares (PLSc), which,
-in contrast to traditional PLS, produces consistent estimates for latent variable models (=~).
-In this case, Mode A weights are transformed to obtain consistent factor loading estimates.
-In addition, the correlations between latent variables and other variables of the structural model are corrected
-for attenuation before they are used to estimate the parameters of the structural model.
-
-- **Inner weighting scheme**: Choose from the following options to calculate inner weights used in the PLS algorithm:
- - Path weighting scheme
- - Centroid weighting scheme
- - Factorial weighting scheme
-
-In case of centroid and factorial inner weighting schemes, the structural model can be ignored in the calculation of the inner weights. In this case not only the adjacent variables are considered but also all other variables of the structural model.
-
-- **Convergence criterion**: Choose from the following options to determine the convergence criterion in the PLS algorithm:
- - Absolute difference between the weights from the current and previous iteration
- - Squared difference between the weights from the current and previous iteration
- - Relative difference between the weights from the current and previous iteration
-
--**Tolerance**: Specify the tolerance level for the convergence criterion.
-
-- **Error calculation method**: Choose from the following options to calculate the standard errors and confidence intervals of the parameter estimates:
- - None
- - Bootstrap
-
-**Samples**: The number of bootstrap runs can be specified.
-
-**Repeatability**: A seed can be set, to make the analysis reproducible.
-
-
-## 3. Output Options
----
-The **Output** section includes options to customize the output you want to generate:
-
-- **R-squared**: Enables output of the coefficients of determination for the dependent constructs.
-- **Additional fit measures**: Enables output of fit measures known from classical SEM are reported such as the SRMR and NFI. Note, these fit measures are calculated based on the PLS estimates (Schuberth et al., 2023)
-- **Mardia's coefficient**:
-- **Reliability measures**: Enables output of reliability measures (Cronbach's alpha, composite reliability, and Dijkstra-Henseler's rho_A) for the latent variables.
-- **Add construct scores to data**: Enable adding the PLS construct scores to the dataset.
-- **Observed indicator correlations**: Enable output of the indicator correlation matrix.
-- **Implied indicator correlations**: Enable output of the model-implied indicator correlation matrix
-- **Observed construct correlations**: Enable output of the construct correlation matrix.
-- **Implied construct correlations**: Enable output of the model-implied construct correlation matrix.
-
-- **Overall model fit** Enables the option to assess the overall fit of the model.
-In particular, bootstrap in combination with various distance measures, i.e., the geodesic distance (dG),
-the standardized root mean square residual (SRMR), the squared Euclidean distance (dL),
-and the distance of the ML fit function (dML) is used to assess
-the discrepancy between the sample correlation matrix and the model-implied counterpart.
-In the literature, this approach is also known as Bollen-Stine bootstrap. If the test statistic value
-is below the critical value the discrepancy is so small that equality between the model-implied
-and the sample correlation matrix can be assumed, that is, the model is a good representation of the structure
-in the population.
- - Bootstrap runs: Specify the number of bootstrap runs
- - significance level: Specify the significance level for the bootstrap test.
- The significance level is used to determine the critical value.
- The critical value is determined as 1-alpha quantile of the bootstrap distance measures.
- - Saturated structural model: Enables the option to assess the overall fit of a model with a saturated structural model.
-
-You can also add **construct scores** to the dataset for further analysis.
-
-## 4. Prediction
----
-The **Prediction** section includes options for predicting endogenous indicator scores using cross-validation:
-
-- **Cross-Validation k-Folds**: Choose the number of k-folds for cross-validation, with a default value of 10.
-- **Repetitions**: Specify the number of repetitions, with a default value of 10.
-
-You can also select a benchmark to compare predictions against:
-- **None**
-- **Linear Model (LM)**
-- **PLS-PM**
-- **GSCA**
-- **PCA**
-- **MAXVAR**
-- **All**
-
-## 5. Output and Interpretation
----
-
-### 5.1 Path Coefficients
-The **path coefficients** represent the strength and direction of the relationships between the constructs. These coefficients are similar to regression weights and help in understanding the impact of one latent variable on another. You can also view the **t-values** and **p-values** to assess the significance of these paths.
-
-### 5.2 Indicator Loadings and Weights
-This section shows the **loadings** of each indicator on its associated construct, which indicates how well each observed variable measures the latent construct. Loadings close to 1 indicate a strong relationship between the indicator and its construct. **Weights** are presented in the case of formative constructs, showing the relative importance of each indicator.
-
-### 5.3 Model Fit Indices
-JASP provides several goodness-of-fit measures to evaluate how well the model fits the data:
-- **SRMR (Standardized Root Mean Square Residual)**: A measure of model fit, where lower values (generally below 0.08) indicate a better fit.
-- **NFI (Normed Fit Index)**: Ranges from 0 to 1, with higher values representing a better fit.
-
-### 5.4 Reliability Measures
-Reliability measures assess the internal consistency of the latent constructs:
-- **Cronbach’s Alpha**: A commonly used reliability coefficient; values above 0.7 generally indicate acceptable reliability.
-- **Composite Reliability (CR)**: A measure of internal consistency similar to Cronbach’s Alpha but considers different factor loadings.
-- **Average Variance Extracted (AVE)**: Represents the amount of variance captured by a construct in relation to the variance due to measurement error. AVE values above 0.5 are generally considered acceptable.
-
-### 5.5 R-Squared (R²)
-The R-squared value represents the proportion of variance in the endogenous constructs explained by the model. Higher values indicate better explanatory power. An R-squared value close to 0.7 is considered substantial, while values around 0.3 are moderate.
-
-### 5.6 Cross-Validated Prediction
-If the cross-validation option is selected, the results will include predicted scores for the endogenous indicators. The k-fold cross-validation helps in assessing the predictive power of the model. You can compare the model’s predictions with benchmarks like linear regression or PLS-PM.
-
-### 5.7 Construct Scores
-You can include the estimated construct scores in the dataset for further analysis. These scores represent the latent variables in the model and can be used for additional analyses outside of SEM.
-
-### 5.8 Bootstrapping Results
-If bootstrapping is used, the output includes **bootstrap confidence intervals** for the path coefficients, loadings, and weights. These intervals help in understanding the stability of the parameter estimates.
-
-### 5.9 Prediction Benchmarks
-If benchmarks are selected, you can compare the PLS-SEM model with:
-- **Linear Model** (LM)
-- **Principal Component Analysis** (PCA)
-- **Generalized Structured Component Analysis** (GSCA)
-- **MAXVAR** (Maximum Variance method)
-
-These benchmarks help in evaluating how well your PLS-SEM model predicts the endogenous variables compared to simpler methods.
-
-References
--------
-- Benitez, J. Henseler, J., Castillo, A., & Schuberth, F. (2020). How to perform and report an impactful analysis using partial least squares: Guidelines for confirmatory and explanatory IS research. *Information & Management, 2*(57), 103-168. doi: 10.1016/j.im.2019.05.003.
-- Dijkstra, T. K., & Henseler, J. (2015). Consistent and asymptotically normal PLS estimators for linear structural equations. *Computational Statistics & Data Analysis 81*, 10–23. doi: 10.1016/j.csda.2014.07.008
-- Evermann, J., & Rönkkö, M. (2021). Recent developments in PLS. *Communications of the Association for Information Systems, 44.* doi: 10.17705/1CAIS.044XX
-- Henseler, J. (2021). *Composite-Based Structural Equation Modeling: Analyzing Latent and Emergent Variables.* New York, Guilford Press.
-- Hair, J.F., Sarstedt, M., Ringle, C.M., & Mena, J.A. (2012). An assessment of the use of partial least squares structural equation modeling in marketing research. *Journal of the Academy of Marketing Science 40*, 414–433. doi: 10.1007/s11747-011-0261-6
-- Rademaker, M.E., & Schuberth, F. (2020). cSEM: Composite-Based Structural Equation Modeling. Package version: 0.4.0, https://m-e-rademaker.github.io/cSEM/.
-- Schuberth, F., Rademaker, M. E., & Henseler, J. (2023). Assessing the overall fit of composite models estimated by partial least squares path modeling. *European Journal of Marketing 57*(6), 1678–1702. doi: 10.1108/EJM-08-2020-0586
-
-### R Packages
----
-- cSEM
-- semTools
diff --git a/inst/help/SEM.md b/inst/help/SEM.md
deleted file mode 100644
index 677a473d..00000000
--- a/inst/help/SEM.md
+++ /dev/null
@@ -1,276 +0,0 @@
-Structural Equation Modeling
-==========================
-
-Perform structural equation modeling (SEM) using `lavaan` (Rosseel, 2012). Go to lavaan.org for tutorials on the model syntax. See also Kline (2015).
-
-For additional reading, see https://osf.io/xkg3j/ for an introduction to SEM in JASP, by Burger & Tanis.
-
-Throughout this help file some terms are used synonymously, these are:
-- latent variables and factors
-- observed variables, manifest variables and indicators
-
-## Input
-### Model window
-Here, users specify their model here in `lavaan` syntax using the names of the variables in their data set (see https://lavaan.ugent.be/tutorial/sem.html). Multiple models can be specified and compared.
-
-- Data: Is the input for the model a raw data matrix with observations as rows and variables in columns, or a variance-covariance matrix with variables in rows and columns. If it is a variance-covariance matrix, the sample size needs to be specified.
-- Sampling weights: Users can choose a variable in their data set that weights each observation.
-
-### Model Options
-- Factor scaling: How should the metric, or scaling, of the latent variables be determined.
- - Factor loadings: Default is by fixing the first indicator loading to 1.
- - Factor variance: fixing the latent variables' variance to 1,
- - Effect coding: fixing the average of loadings per latent variable to 1,
- - None
-- Include mean structure: Should observed or latent intercepts be estimated. In SEM, observed means are called intercepts and latent means are called means. To identify the model, some elements need to be fixed:
- - Fix latent means to zero: Default, observed means will be estimated freely.
- - Fix observed intercepts to zero: Latent means will be estimated freely.
- - Fix mean of manifest intercepts to zero: Latent means will be estimated freely.
-- Assume factors uncorrelated: By default the factors are assumed to correlate if not specified differently in the model window. This checkbox changes that and factors are estimated to be orthogonal.
-
-- Fix exogenous covariates: If checked, the exogenous covariates are considered fixed variables and the means, variances and covariances of these variables are fixed to their sample values. If not checked, they are considered random, and the means, variances and covariances are free parameters.
-- Omit residual single indicator: If checked, the residual variance (if included) of an observed indicator is set to zero if it is the only indicator of a latent variable.
-- Include residual variances: If checked, the (residual) variances of both observed and latent variables are free to-be-estimated parameters.
-- Correlate exogenous latents: If checked, the covariances of exogenous latent variables are included in the model and set free.
-- Correlate dependent variables: If checked, the covariances of dependent variables (both observed and latent) are included in the model and set free.
-- Add thresholds: If checked, thresholds for limited (non-continuous) dependent variables are included in the model and set free.
-- Add scaling parameters: If checked, response scaling parameters for limited (non-continuous) dependent variables are included in the model and set free.
-- Constrain EFA blocks: If checked, the necessary constraints are imposed to make the (unrotated) exploratory factor analysis blocks identifiable: for each block, factor variances are set to 1, factor covariances are constrained to be zero, and factor loadings are constrained to follow an echelon pattern.
-
-### Estimation Options
-- Estimator: Some estimators imply options for test and standard error. If test and standard error remains as "default", they will be either standard or set by the chosen estimator. If test and standard error are specified (meaning not default) they will overwrite whatever option the estimator implies.
- - Default: The estiamtor will be determined by other options, as well as the scaling of the variables (usually becomes ML)
- - ML: Maximum Likelihood
- - GLS: Generalized Least Squares
- - WLS: Weighted Least Squares
- - ULS: Unweighted Least Squares
- - DWLS: Diagonally Weighted Least Squares
- - DLS: Distributionally Weighted Least Squares
- - PML: Pairwise maximum likelihood
- - Extensions of ML-estimators with extra effects:
- - MLM: classic robust se (se="robust.sem"), Satorra-Bentler test statistic (test="satorra.bentler")
- - MLMV: classic robust se, scaled and shifted test statistic (test="scaled.shifted")
- - MLMVS: classic robust se, mean and var adjusted Satterthwaite style test statistic (test="mean.var.adjusted")
- - MLF: first-order standard se (information="first.order"), standard test
- - MLR: Huber-White robust se (se="robust.huber.white"), Yuan-Bentler T2-star test statistic (test="yuan.bentler.mplus")
- - Others:
- - WLSM: implies DWLS with scaled test and robust se
- - WLSMV: implies DWLS with mean and var adjusted test and robust se
- - ULSM: implies ULS with scaled test and robust se
- - ULSMV: implies ULS with mean-var adjusted test and robust se
-
-- Model test:
- - Default: The test will be determined by other options (estimator, missing, mimic), as well as the scaling of the variables (usually becomes standard)
- - Standard: Chisq test statistic
- - Satorra-Bentler: scaled test statistic
- - Yuan-Bentler: scaled test statistic
- - Yuan-Bentler Mplus: asymptotically equal to Yuan-Bentler scaled test statistic
- - Mean and variance adjusted: test statistic, also called "Satterthwaite"
- - Scaled and shifted: test statistic
- - Bootstrap (Bollen-Stine): The Bollen-Stine bootstrap is used to compute the bootstrap probability value of the (regular) test statistic. If chosen, a field with the number of bootstrap samples appears.
- - Browne residual based (ADF): Browne's residual-based test statistic using ADF (asymptocially distribution free) theory is computed.
- - Browne residual based (NT): Browne's residual-based test statistic using normal theory is computed.
-
-- Information matrix: Matrix used to compute the standard errors
- - Default: The information matrix will be determined by other options (estimator, missing, mimic), as well as the scaling of the variables (usually becomes expected)
- - Expected
- - Observed
- - First order: The information matrix is based on the outer product of the casewise scores
-
-- Standard errors:
- - Default: The standard errors method will be determined by other options (estimator, missing, mimic), as well as the scaling of the variables (usually becomes expected)
- - Standard: Conventional standard errors are computed based on inverting the (expected, observed or first.order) information matrix
- - Robust: conventional robust standard errors are computed (also called robust.sem)
- - Robust Huber-White: Standard errors are computed based on the 'mlr' (aka pseudo ML, Huber-White) approach
- - Bootstrap: Standard errors are computed from bootstrapped model fit objects.
- - Bootstrap samples: Number of bootstrap samples to take for the standard errors
-
-- Confidence intervals: CI width for the parameter estimates
-- Standardize variables before estimation: z-standardizes all variables before estimation
-- Missing data handling: How to treat missings
- - Listwise: Exclude cases that have missings
- - FIML: Use full-information maximum likelihood, only available for ML estimation, also called "ml" sometimes
- - Pairwise: In the first step, compute thresholds (for categorical variables) and means or intercepts (for continuous variables) using univariate information only. In this step, we simply ignore the missing values just like in mean(x, na.rm = TRUE). In the second step, we compute polychoric/polyserial/pearson correlations using (only) two variables at a time. Here we use pairwise deletion: we only keep those observations for which both values are observed (not-missing).
- - Two-stage: In this approach, we first estimate the sample statistics (mean vector, variance-covariance matrix) using an EM algorithm. Then, we use these estimated sample statistics as input for a regular analysis (as if the data were complete). The standard errors and test statistics are adjusted correctly to reflect the two-step procedure. For continuous data.
- - Robust two-stage: Same as two-stage but option produces standard errors and a test statistic that are robust against non-normality. For continuous data.
- - Doubly robust: For estimator PML.
-
-### Output Options
-- Additional fit measures: Produce a table with a variety of fit measures
-- R-squared: Produces a table with the explained variance in each indicator
-- Average variance extracted (AVE): The amount of variance that is captured by a construct in relation to the amount of variance due to measurement error. It is used to evaluate the convergent validity of a construct.
-- Heterotrait-monotrait ratio (HTMT): Discriminant validity. Assessing the degree to which constructs are distinct from each other by comparing the correlations between different constructs (heterotrait) to the correlations within the same construct (monotrait).
-- Reliability measures: Metrics used to assess the consistency and stability of a measurement instrument, such as coefficient alpha and composite(omega) reliability.
-- Observed covariances: Covariances calculated directly from the observed data
-- Implied covariances: Covariances predicted by the SEM model based on the estimated parameters, representing the model's expectations of how the variables should covary if the model is correct.
-- Residual covariances: Differences between the observed covariances and the implied covariances, indicating how well the model fits the data.
-- Standardized residuals: Covariance matrix of standardized residuals
-- Mardia's coefficient: A measure of multivariate normality, including skewness and kurtosis components, used to assess whether the data follow a multivariate normal distribution.
-- Standardized estimates: Should the output show standardized parameter estimates
- - All: The standardized estimates are based on both the variances of both (continuous) observed and latent variables.
- - Latents: The standardized estimates are on the variances of the (continuous) latent variables only.
- - Except exogenous covariates: The standardized estimates are based on both the variances of both (continuous) observed and latent variables, but not the variances of exogenous covariates.
-- Path diagram: Plots the model
- - Show parameter estimates
- - Show legend
-- Modification indices: Show the modification indices, that is, the possible improvement indications of the model test statistic
- - Hide low indices: Hide indices below a certain "Threshold" value that are unimportant for the improvement of the model
-- Show warnings: Show warnings produced by the underlying R-package (if there are any)
-
-### Multigroup SEM
-- Grouping variable: Fit the model for mutliple groups. Variable needs to be a variable that is either nominally or ordinally scaled.
-- Equality constraints: Constraints chosen here are fixed to be equal across all groups
- - Loadings, Intercepts, Residuals, Resdiaul covariances, Means (intercepts), Threshiolds, Regressions, Latent variances, Latent covariances
-- Release constraints (one per line): Text input to release constraints, needs to be written in lavaan syntax, for instance, for releasing a single loading of indicator x2 on factor f, write `f=~x2`
-
-
-# Sensitivity Analysis
-- Run sensitivity analysis: Conduct sensitivity analysis for structural equation modeling (SEM) against a potential missing confounder. A potential missing confounder is specified as a simulated phantom variable, a latent variable without manifest indicators, such that the sensitivity of SEM can be assessed through comparing results from models with and without the phantom variable.
-- Search algorithm: How to optimally sample the phantom variables
- - Ant colony optimization: Method for finding good paths through graphs
- - Number of ants: How many artificial ants are used in each iteration of the algorithm. Each ant represents a potential solution to the optimization problem
- - Size of the solution archive: The number of best solutions that are stored and maintained during the optimization process
- - Convergence rate threshold: During each iteration of the optimization algorithm, the change in the objective function or the parameters is measured. If this change is smaller than the convergence rate threshold, the algorithm is considered to have converged, and the iteration stops
- - Tabu search: Maintains a list of recently visited solutions (or moves) called the "tabu list" to prevent revisiting them and getting stuck in local optima
-- Optimizer function: Function that is maximized during the optimization
- - % change mean estimate
- - SD of deviance /(divided by) old estimate
- - Change of p-value
- - Distance of p-value from alpha
- - Change of RMSEA
- - Distance of RMSEA from 0.05
-- Significance level
-- Maximum number of iterations
-- Repeatability: Set seed to guarantee reproducible results
-
-## Output
-
-- Model fit
- - Model(s)
- - Group (optional)
- - AIC (optional): Akaike information criterion, the smaller the better
- - BIC (optional): Bayesian information criterion, the smaller the better
- - n(Observations): Number of observations used in fitting the model
- - n(Parameters): Total are the number of freely estimated parameters ignoring contraints, Free are the freely estimated parameters taking constraints into account
- - Baseline test (likelihood ratio): H0 user-specified and saturated model are the same, H1 models differ.
- - X^2: Chi-square distributed test statistic
- - df_ degrees of freedom of the model chi-square test
- - p: p-value for the comparison user-specified model against the saturated model. We check if the saturated model is significantly different from the user-specified model and if so, we reject the user-specified model.
- - Difference test (likelihood ratio): H0 Models are the same, H1 models differ
- - delta(X^2): Difference in test statistic values between two or more models
- - delta(df): Difference in df between two models or more
- - p: p-value for the comparison of the two or more models. H0: Models are the same, H1: models differ. Checks if the models with fewer df (more complex) differ significantly from the models with more df (simpler). If significant, the model with more df is rejected. If not significant, the model with more df is retained
-
-#### Additional Fit Measures (optional)
-- Fit indices
- - Comparative Fit Index (CFI): How well a user-specified model fits the data compared to a null model; the closer to 1 the better.
- - Tucker-Lewis Index (TLI): Compares the fit of a specified model to a null model, adjusting for model complexity; the closer to 1 the better.
- - Bentler-Bonett Non-normed Fit Index (NNFI): Similar to TLI, it adjusts for model complexity and is less sensitive to sample size; the closer to 1 the better.
- - Bentler-Bonett Normed Fit Index (NFI): Compares the fit of a specified model to a null model without adjusting for model complexity; the closer to 1 the better.
- - Parsimony Normed Fit Index (PNFI): Adjusts the NFI for model complexity, rewarding simpler models; the closer to 1 the better.
- - Bollen's Relative Fit Index (RFI): Compares the fit of a specified model to a null model, similar to NFI but with different scaling; the closer to 1 the better.
- - Bollen's Incremental Fit Index (IFI): Measures the improvement in fit of a specified model over a null model, adjusting for degrees of freedom; the closer to 1 the better.
- - Relative Noncentrality Index (RNI): Similar to the CFI, it compares the fit of a specified model to a null model, adjusting for noncentrality; the closer to 1 the better.
- - Root mean square error of approximation (RMSEA): Measures the discrepancy of the model from the data per degree of freedom, with lower values indicating a better fit.
- - RMSEA 90% CI lower bound: The lower bound of the 90% confidence interval for the RMSEA.
- - RMSEA 90% CI upper bound: The upper bound of the 90% confidence interval for the RMSEA.
- - RMSEA p-value: The p-value associated with the RMSEA, testing the null hypothesis that the RMSEA is less than or equal to 0.05.
- - Standardized root mean square residual (SRMR): Measures the standardized difference between observed and model predicted correlations, with lower values indicating a better fit.
- - Hoelter's critical N (α = .05): The sample size at which the chi-square test would no longer be significant at the 0.05 level.
- - Hoelter's critical N (α = .01): The sample size at which the chi-square test would no longer be significant at the 0.01 level.
- - Goodness of fit index (GFI): Measures the proportion of variance accounted for by the estimated population covariance, with values closer to 1 indicating a better fit.
- - McDonald fit index (MFI): A fit index that adjusts for model complexity and sample size, with values closer to 1 indicating a better fit.
- - Expected cross validation index (ECVI): Estimates the fit of the model to a new sample of the same size, with lower values indicating a better fit.
- - Log-likelihood: The log of the likelihood function, used in model comparison.
- - Number of free parameters: The number of parameters estimated freely in the model.
- - Akaike Information Criterion (AIC): A measure of model fit that penalizes for model complexity, with lower values indicating a better fit.
- - Bayesian Information Criterion (BIC): Similar to AIC but with a stronger penalty for model complexity, with lower values indicating a better fit.
- - Sample-size adjusted Bayesian Information Criterion (SSABIC): A version of BIC adjusted for sample size, with lower values indicating a better fit.
-
-- T-size fit indices: Equvalence testing: Testing for close fit instead of exact fit
- - T-size: (minimum tolerable size) of misspecification for the model(s): T-size versions of CFI and RMSEA
- - poor-fair limit: For CFI, below this limit the model fit becomes poor. For RMSEA, above this limit the model fit becomes poor.
- - fair-close limit: For the CFI, above this limit the model fit becomes close (good). For the RMSEA; below this limit the model fit becomes close (good)
-
-- R-Squared (optional)
- - Explained variance in dependent variables by their predictors
-
-- Average variance extracted (optional)
- - Amount of variance captured by a construct (latent variable)
-
-- Heterotrait-Monotrait Ratio (optional)
- - Correlations of constructs, that is, latent variables
-
-- Reliability (optional)
- - Reliability per latent variable: that is, how reliably measured are the indicators for that latent variable
- - total: How reliably measured is the full set of indicators
- - Coefficient alpha: The closer to 1 the better. Also called Cronbach's alpha. Best for unidimensional constructs.
- - Coefficient omega: The closer to 1 the better. The *total* value denotes omega_t.
-
-- Mardias coefficients:
- - Skewness: H0 multivariate skewness is equal to the normal distribution
- - Kurtosis: H0 multivariate kurtosis is equal to the normal distribution
-
-#### Parameter Estimates
-- Factor loadings (and others, the logic stays the same)
- - Group (optional)
- - Latent: Name of latent variable(s)
- - Indicator: Name of manifest variables
- - Label (optional, not visible column name): Shows the labels of equality constraints
- - Estimate: when standardized estimate is checked this becomes "Std.estimate"
- - Std.error
- - z-value: of the standard normal distribution
- - p: -value
- - X% Confidence interval: lower and upper bound
-
-- Regression coefficients: Outcome and predictor
-- Factor variances
-- Factor covariances
-- Residual variances: Unexplained variance in the indicators
-- Intercepts (optional): Estimated means of observed and latent variables
-- Total effects (optional): Summarize the regression paths per variable
-- Indirect effects (optional): Regression paths through other variables
-- Observed covariance matrix (optional)
-- Implied covariance matrix (optional): model-implied
-- Residuals covariance matrix
-- Standardized residuals covariance matrix
-
-- Modification indices (optional):
- - First three columns contain the specification that could be made in the model syntax
- - mi: modification index. How much better would the model fit. Sorted from high to low.
- - epc: expected parameter change
- - sepc: expected parameter change for standardized estimates: lv, all, and no exogenous covariates (nox)
-
-- Path diagram (optional)
-
-#### Sensitivity Analysis
-- Summary of sensitivity analysis:
- - Path: Which path would be affected (only regressions)
- - Original model: Summaries of the path(s) for the original model
- - Sensitivtiy model:
- - p*: new p-value with phantom variable(s)
- - Mean, Min, and Max of the path estimate with the phantom variable(s)
-
-- Sensitivity parameters that led to a change in significance
- - Path
- - Sensitivity parameters: The path estimates for the phantom variable(s)
-
-- Summary of sensitivity parameters
- - Sensitivity parameter: Path between phantom variable and latent variable(s)
-
-
-References
--------
-- Hu, L. T., & Bentler, P. M. (1999). Cutoff criteria for fit indexes in covariance structure analysis: Conventional criteria versus new alternatives. *Structural Equation Modeling: A Multidisciplinary Journal, 6*(1), 1-55, https://doi.org/10.1080/10705519909540118
-- Katerina M. Marcoulides & Ke-Hai Yuan (2017). New ways to evaluate goodness of fit: A note on using equivalence testing to assess structural equation models. *Structural Equation Modeling: A Multidisciplinary Journal, 24*(1), 148-153, https://doi.org/10.1080/10705511.2016.1225260
-- Kline, R. B. (2015). Principles and practice of structural equation modeling. *Guilford Publications*.
-- Rosseel, Y. (2012). lavaan: An R Package for Structural Equation Modeling. *Journal of Statistical Software, 48*(2), 1-36, https://doi.org/10.18637/jss.v048.i02
-- Shen, Z., & Leite, W. L. (2022). SEMsens: An R package for sensitivity analysis of structural equation models with the ant colony optimization algorithm. *Applied Psychological Measurement, 46*(2), 159-161. https://doi.org/10.1177/01466216211063233
-
-### R Packages
----
-- lavaan
-- semPlot
-- SEMsens
-- semTools
-- stats
diff --git a/inst/help/SEM_nl.md b/inst/help/SEM_nl.md
deleted file mode 100644
index 8f3bac9b..00000000
--- a/inst/help/SEM_nl.md
+++ /dev/null
@@ -1,18 +0,0 @@
-Structural Equation Modeling
-==========================
-
-Voer structural equation modeling (SEM) uit door middel van `lavaan` (Rosseel, 2012). Ga naar lavaan.org voor uitleg over de syntax van het model. Zie ook Kline (2015).
-
-Zie https://osf.io/xkg3j/ voor een introductie van SEM in JASP van Burger & Tanis.
-
-Referenties
--------
-- Kline, R. B. (2015). Principles and practice of structural equation modeling. *Guilford publications*.
-- Rosseel, Y. (2012). lavaan: An R Package for Structural Equation Modeling. *Journal of Statistical Software, 48*(2), 1-36. URL www.jstatsoft.org/v48/i02/
-
-### R Packages
----
-- lavaan
-- semPlot
-- semTools
-- stats
diff --git a/inst/help/forQml/tooltipEstimators.md b/inst/help/forQml/tooltipEstimators.md
deleted file mode 100644
index e7e07e47..00000000
--- a/inst/help/forQml/tooltipEstimators.md
+++ /dev/null
@@ -1,21 +0,0 @@
-
-### Help on Estimators
-Some of the estimators come with options that are set in the background and may be hidden for the user:
-
-- Estimators without extra effects:
- - ML, GLS, WLS, ULS, DWLS, DLS
-
-- Extensions of ML-estimators with extra effects:
- - MLM: classic robust se (se="robust.sem"), Satorra-Bentler test statistic (test="satorra.bentler")
- - MLMV: classic robust se, scaled and shifted test statistic (test="scaled.shifted")
- - MLMVS: classic robust se, mean and var adjusted Satterthwaite style test statistic (test="mean.var.adjusted")
- - MLF: first-order standard se (information="first.order"), standard test
- - MLR: Huber-White robust se (se="robust.huber.white"), Yuan-Bentler T2-star test statistic (test="yuan.bentler.mplus")
-
-- Others:
- - WLSM: implies DWLS with scaled test and robust se
- - WLSMV: implies DWLS with mean and var adjusted test and robust se
- - ULSM: implies ULS with scaled test and robust se
- - ULSMV: implies ULS with mean-var adjusted test and robust se
-
-- Note: If you specify "Model test" or "Standard errors" the corresponding options set by the estimators in the background will be overwritten
\ No newline at end of file
diff --git a/inst/help/forQml/tooltipFitIndices.md b/inst/help/forQml/tooltipFitIndices.md
deleted file mode 100644
index 96e9055d..00000000
--- a/inst/help/forQml/tooltipFitIndices.md
+++ /dev/null
@@ -1,7 +0,0 @@
-
-### Help on Fit Indices
-
-The T-size equivalents of the conventional CFI cut-off values (poor < 0.90 < fair < 0.95 < close) are
-
-Hu, L. T., & Bentler, P. M. (1999). Cutoff criteria for fit indexes in covariance structure analysis: Conventional criteria versus new alternatives. *Structural Equation Modeling: A Multidisciplinary Journal, 6*(1), 1-55, https://doi.org/10.1080/10705519909540118
-Katerina M. Marcoulides & Ke-Hai Yuan (2017) New Ways to Evaluate Goodness of Fit: A Note on Using Equivalence Testing to Assess Structural Equation Models. *Structural Equation Modeling: A Multidisciplinary Journal, 24*(1), 148-153, https://doi.org/10.1080/10705511.2016.1225260
diff --git a/inst/qml/MediationAnalysis.qml b/inst/qml/MediationAnalysis.qml
index 486d6f26..3b30029b 100644
--- a/inst/qml/MediationAnalysis.qml
+++ b/inst/qml/MediationAnalysis.qml
@@ -36,6 +36,7 @@ Form
title: qsTr("Predictors")
name: "predictors"
id: predictors
+ info: qsTr("One or multiple predictor variables predicting the mediators and the outcome variables.")
}
AssignedVariablesList
{
@@ -44,7 +45,7 @@ Form
allowedColumns: ["scale", "ordinal"]
allowTypeChange: true
id: mediators
-
+ info: qsTr("Variables through which the indirect effect of the predictors on the outcomes is hypothesized to flow.")
}
AssignedVariablesList
{
@@ -53,18 +54,21 @@ Form
allowedColumns: ["scale", "ordinal"]
allowTypeChange: true
id: outcomes
+ info: qsTr("Variables predicted by the predictors and the mediators.")
}
AssignedVariablesList
{
title: qsTr("Background confounders")
name: "confounds"
id: confounds
+ info: qsTr("Variables explaining the predictors, mediators, and outcomes. Direct, indirect, and total effects are estimated conditional on these variables.")
}
}
Section
{
title: qsTr("Options")
+ info: qsTr("Options for standardization, additional parameter estimates, and model display.")
ColumnLayout
{
Group
@@ -72,23 +76,26 @@ Form
CheckBox
{
name: "standardizedEstimate"; label: qsTr("Standardized estimates");
+ info: qsTr("Standardize all variables (mean = 0, sd = 1) before estimation.")
RadioButtonGroup
{
name: "standardizedEstimateType"
- RadioButton { value: "all"; label: qsTr("All"); checked: true }
- RadioButton { value: "latents"; label: qsTr("Latents") }
- RadioButton { value: "nox"; label: qsTr("Except exogenous covariates") }
+ info: qsTr("Type of standardization.")
+ RadioButton { value: "all"; label: qsTr("All"); checked: true; info: qsTr("Standardize based on variances of both observed and latent variables.") }
+ RadioButton { value: "latents"; label: qsTr("Latents"); info: qsTr("Standardize based on latent variable variances only.") }
+ RadioButton { value: "nox"; label: qsTr("Except exogenous covariates"); info: qsTr("Standardize excluding exogenous covariates.") }
}
}
- CheckBox { label: qsTr("Lavaan syntax") ; name: "syntax" }
- CheckBox { label: qsTr("R-squared") ; name: "rSquared" }
+ CheckBox { label: qsTr("Lavaan syntax"); name: "syntax"; info: qsTr("Display the lavaan syntax used to estimate the model.") }
+ CheckBox { label: qsTr("R-squared"); name: "rSquared"; info: qsTr("Display the proportion of variance explained for each endogenous variable.") }
}
Group
{
title: qsTr("Additional parameter estimates")
- CheckBox { label: qsTr("Total indirect effects"); name: "totalIndirectEffect"; checked: true }
- CheckBox { label: qsTr("Residual covariances"); name: "residualCovariance"; checked: true }
- CheckBox { label: qsTr("Path coefficients"); name: "pathCoefficient"; checked: true }
+ info: qsTr("Additional parameter estimate tables to display.")
+ CheckBox { label: qsTr("Total indirect effects"); name: "totalIndirectEffect"; checked: true; info: qsTr("Display total indirect effects summed across all mediators.") }
+ CheckBox { label: qsTr("Residual covariances"); name: "residualCovariance"; checked: true; info: qsTr("Display residual covariances between variables.") }
+ CheckBox { label: qsTr("Path coefficients"); name: "pathCoefficient"; checked: true; info: qsTr("Display the path coefficients of the model.") }
}
}
// create a string with all variables types to pass to the error calc elements
@@ -100,12 +107,14 @@ Form
Section
{
text: qsTr("Plots")
+ info: qsTr("Options for generating plots of the mediation model.")
CheckBox {
text: qsTr("Model plot")
name: "pathPlot"
id: pathPlot
- CheckBox { text: qsTr("Parameter estimates") ; name: "pathPlotParameter" }
- CheckBox { text: qsTr("Legend") ; name: "pathPlotLegend" }
+ info: qsTr("Display a path diagram of the mediation model.")
+ CheckBox { text: qsTr("Parameter estimates") ; name: "pathPlotParameter"; info: qsTr("Display parameter estimates on the path diagram.") }
+ CheckBox { text: qsTr("Legend") ; name: "pathPlotLegend"; info: qsTr("Display a legend in the path diagram.") }
}
}
diff --git a/inst/qml/Mimic.qml b/inst/qml/Mimic.qml
index 44b0f230..0f55d6a4 100644
--- a/inst/qml/Mimic.qml
+++ b/inst/qml/Mimic.qml
@@ -37,34 +37,39 @@ Form
title: qsTr("Indicators")
name: "indicators"
allowedColumns: ["scale", "ordinal"]
+ info: qsTr("Observed indicator variables that define the latent variable in the MIMIC model.")
}
AssignedVariablesList
{
title: qsTr("Predictors")
name: "predictors"
allowedColumns: []
+ info: qsTr("Observed predictor variables (causes) that directly influence the latent variable.")
}
}
Section
{
title: qsTr("Options")
+ info: qsTr("Options for standardization, model syntax display, and additional output.")
Group
{
CheckBox
{
name: "standardizedEstimate"; label: qsTr("Standardized estimates");
+ info: qsTr("Standardize all variables (mean = 0, sd = 1) before estimation.")
RadioButtonGroup
{
name: "standardizedEstimateType"
- RadioButton { value: "all"; label: qsTr("All"); checked: true }
- RadioButton { value: "latents"; label: qsTr("Latents") }
- RadioButton { value: "nox"; label: qsTr("Except exogenous covariates") }
+ info: qsTr("Type of standardization.")
+ RadioButton { value: "all"; label: qsTr("All"); checked: true; info: qsTr("Standardize based on variances of both observed and latent variables.") }
+ RadioButton { value: "latents"; label: qsTr("Latents"); info: qsTr("Standardize based on latent variable variances only.") }
+ RadioButton { value: "nox"; label: qsTr("Except exogenous covariates"); info: qsTr("Standardize excluding exogenous covariates.") }
}
}
- CheckBox { label: qsTr("Lavaan syntax") ; name: "syntax" }
- CheckBox { label: qsTr("R-squared") ; name: "rSquared" }
- CheckBox { label: qsTr("Additional fit measures") ; name: "additionalFitMeasures" }
+ CheckBox { label: qsTr("Lavaan syntax") ; name: "syntax"; info: qsTr("Display the lavaan syntax used to estimate the model.") }
+ CheckBox { label: qsTr("R-squared") ; name: "rSquared"; info: qsTr("Display the proportion of variance explained for each endogenous variable.") }
+ CheckBox { label: qsTr("Additional fit measures") ; name: "additionalFitMeasures"; info: qsTr("Display additional fit indices for evaluating model fit (e.g., CFI, TLI, RMSEA, SRMR).") }
}
Common.ErrorCalculation{}
@@ -74,13 +79,15 @@ Form
Section
{
text: qsTr("Plots")
+ info: qsTr("Options for generating plots of the MIMIC model.")
CheckBox
{
text: qsTr("Model plot")
name: "pathPlot"
- id: pathPlot
- CheckBox { text: qsTr("Parameter estimates") ; name: "pathPlotParameter" }
- CheckBox { text: qsTr("Legend") ; name: "pathPlotLegend" }
+ id: pathPlot
+ info: qsTr("Display a path diagram of the MIMIC model.")
+ CheckBox { text: qsTr("Parameter estimates") ; name: "pathPlotParameter"; info: qsTr("Display parameter estimates on the path diagram.") }
+ CheckBox { text: qsTr("Legend") ; name: "pathPlotLegend"; info: qsTr("Display a legend in the path diagram.") }
}
}
diff --git a/inst/qml/ModeratedNonLinearFactorAnalysis.qml b/inst/qml/ModeratedNonLinearFactorAnalysis.qml
index 62686e2b..a6ec618a 100644
--- a/inst/qml/ModeratedNonLinearFactorAnalysis.qml
+++ b/inst/qml/ModeratedNonLinearFactorAnalysis.qml
@@ -60,6 +60,7 @@ Form
initNumberFactors: 1
allowedColumns: ["scale"]
keepAvailableVariables: true
+ info: qsTr("Define latent factors and assign observed indicator variables to each factor.")
}
Section
@@ -67,6 +68,7 @@ Form
title: qsTr("Moderation")
expanded: true
id: mod
+ info: qsTr("Specify moderator variables and their effects on measurement model parameters.")
VariablesForm
{
@@ -82,6 +84,7 @@ Form
allowedColumns: ["scale", "nominal"]
title: qsTr("Moderators")
name: "moderators"
+ info: qsTr("Variables hypothesized to moderate the measurement model parameters. Continuous moderators can optionally include squared and cubic effects.")
rowComponentTitle: qsTr("Square Cubic")
rowComponent: RowLayout
{
@@ -90,12 +93,14 @@ Form
name: "moderatorSquaredEffect"
id: squared
visible: moderators.getVariableType(rowValue) === columnTypeScale
+ info: qsTr("Include a quadratic (squared) effect for this moderator.")
}
CheckBox
{
name: "moderatorCubicEffect"
id: cubic
visible: moderators.getVariableType(rowValue) === columnTypeScale
+ info: qsTr("Include a cubic effect for this moderator.")
}
}
}
@@ -105,6 +110,7 @@ Form
name: "syncAnalysisBox"
label: qsTr("Start/Sync Analysis")
checked: false
+ info: qsTr("Click to start or synchronize the analysis. The analysis does not run automatically due to computational intensity.")
Component.onCompleted:
{
background.color = "#ffcb98"
@@ -115,6 +121,7 @@ Form
Group
{
title: qsTr("Assumption Check")
+ info: qsTr("Check measurement invariance assumptions by testing model fit across groups defined by the moderator variables.")
CheckBox
{
name: "checkModelFitPerGroup";
@@ -122,6 +129,7 @@ Form
label: qsTr("Check model fit per group");
id: fitPerGroup;
enabled: moderators.columnsNames != ""
+ info: qsTr("Fit the measurement model separately in each group to verify that the model fits adequately before testing moderation.")
}
IntegerField
{
@@ -130,8 +138,9 @@ Form
defaultValue: 2;
enabled: fitPerGroup.checked;
min: 2
+ info: qsTr("Number of groups into which continuous moderator variables are split for the assumption check.")
}
- CheckBox { name: "addGroupVariableToData"; label: qsTr("Add group variable to data"); enabled: fitPerGroup.checked }
+ CheckBox { name: "addGroupVariableToData"; label: qsTr("Add group variable to data"); enabled: fitPerGroup.checked; info: qsTr("Save the group variable created by splitting the continuous moderator to the dataset.") }
}
ColumnLayout
@@ -148,6 +157,7 @@ Form
addItemManually: false
values: combinePairs(moderators.columnsNames)
headerLabels: [qsTr("Include")]
+ info: qsTr("Include interaction terms between pairs of moderators.")
rowComponent: RowLayout
{
Text { text: rowValue; Layout.preferredWidth: 150 * jaspTheme.uiScale }
@@ -161,6 +171,7 @@ Form
{
id: invOpts
title: qsTr("Moderation Options")
+ info: qsTr("Configure invariance test levels and specify which individual parameters should be tested for moderation.")
// property var names: []
@@ -168,11 +179,12 @@ Form
{
columns: 1
title: qsTr("Invariance Tests")
- CheckBox { name: "invarianceTestConfigural" ; checked: false ; label: qsTr("Configural"); id: invarianceTestConfigural }
- CheckBox { name: "invarianceTestMetric" ; checked: false ; label: qsTr("Metric"); id: invarianceTestMetric }
- CheckBox { name: "invarianceTestScalar" ; checked: false ; label: qsTr("Scalar"); id: invarianceTestScalar }
- CheckBox { name: "invarianceTestStrict" ; checked: false ; label: qsTr("Strict"); id: invarianceTestStrict }
- CheckBox { name: "invarianceTestCustom" ; checked: false; label: qsTr("Custom"); id: invarianceTestCustom }
+ info: qsTr("Select the levels of measurement invariance to test. Each level constrains an additional set of parameters to be equal across moderator values.")
+ CheckBox { name: "invarianceTestConfigural" ; checked: false ; label: qsTr("Configural"); id: invarianceTestConfigural; info: qsTr("Test configural invariance: same factor structure across groups but all parameters free.") }
+ CheckBox { name: "invarianceTestMetric" ; checked: false ; label: qsTr("Metric"); id: invarianceTestMetric; info: qsTr("Test metric invariance: constrain factor loadings to be equal across groups.") }
+ CheckBox { name: "invarianceTestScalar" ; checked: false ; label: qsTr("Scalar"); id: invarianceTestScalar; info: qsTr("Test scalar invariance: constrain factor loadings and intercepts to be equal across groups.") }
+ CheckBox { name: "invarianceTestStrict" ; checked: false ; label: qsTr("Strict"); id: invarianceTestStrict; info: qsTr("Test strict invariance: constrain factor loadings, intercepts, and residual variances to be equal across groups.") }
+ CheckBox { name: "invarianceTestCustom" ; checked: false; label: qsTr("Custom"); id: invarianceTestCustom; info: qsTr("Define a custom set of parameter constraints for invariance testing.") }
}
property var firstLayerValues: [invarianceTestConfigural, invarianceTestMetric, invarianceTestScalar, invarianceTestStrict, invarianceTestCustom].filter(x => x.checked).map(x => ({value: x.name, label: x.label}))
@@ -189,6 +201,7 @@ Form
optionKeyLabel: "keyLabel"
id: modFirstLayer
addItemManually: false
+ info: qsTr("For each invariance level, specify which individual measurement parameters should be tested for moderation effects.")
rowComponent: TabView
{
id: modSecondLayer
@@ -242,10 +255,12 @@ Form
Section
{
title: qsTr("Output Options")
+ info: qsTr("Select additional output tables and parameter estimates to display.")
Group
{
title: qsTr("Parameter Estimates")
+ info: qsTr("Select which measurement model parameter estimates to display in the output.")
DoubleField
{
name: "parameterEstimatesAlphaLevel"
@@ -253,17 +268,18 @@ Form
negativeValues: false
decimals: 4
defaultValue: 0.05
+ info: qsTr("Significance level for flagging parameter estimates.")
}
- CheckBox { name: "parameterEstimatesLoadings"; label: qsTr("Loadings") }
- CheckBox { name: "parameterEstimatesIntercepts"; label: qsTr("Intercepts") }
- CheckBox { name: "parameterEstimatesResidualVariances"; label: qsTr("Residual variances") }
- CheckBox { name: "parameterEstimatesFactorVariance"; label: qsTr("Factor variances") }
- CheckBox { name: "parameterEstimatesFactorMeans"; label: qsTr("Factor means") }
- CheckBox { name: "parameterEstimatesFactorCovariances"; label: qsTr("Factor covariances") }
+ CheckBox { name: "parameterEstimatesLoadings"; label: qsTr("Loadings"); info: qsTr("Display factor loading estimates.") }
+ CheckBox { name: "parameterEstimatesIntercepts"; label: qsTr("Intercepts"); info: qsTr("Display intercept estimates for observed indicators.") }
+ CheckBox { name: "parameterEstimatesResidualVariances"; label: qsTr("Residual variances"); info: qsTr("Display residual variance estimates for observed indicators.") }
+ CheckBox { name: "parameterEstimatesFactorVariance"; label: qsTr("Factor variances"); info: qsTr("Display latent factor variance estimates.") }
+ CheckBox { name: "parameterEstimatesFactorMeans"; label: qsTr("Factor means"); info: qsTr("Display latent factor mean estimates.") }
+ CheckBox { name: "parameterEstimatesFactorCovariances"; label: qsTr("Factor covariances"); info: qsTr("Display latent factor covariance estimates.") }
}
- CheckBox { label: qsTr("Show syntax") ; name: "showSyntax" }
+ CheckBox { label: qsTr("Show syntax") ; name: "showSyntax"; info: qsTr("Display the lavaan syntax used to estimate the model.") }
}
@@ -272,6 +288,7 @@ Form
{
title: qsTr("Plots")
id: plots
+ info: qsTr("Configure marginal effects plots showing how measurement parameters change as a function of the moderator variables.")
TabView
{
diff --git a/inst/qml/PLSSEM.qml b/inst/qml/PLSSEM.qml
index f666f9bf..6d525b42 100644
--- a/inst/qml/PLSSEM.qml
+++ b/inst/qml/PLSSEM.qml
@@ -32,6 +32,7 @@ Form
maximumItems: 1
newItemName: qsTr("Model")
optionKey: "name"
+ info: qsTr("Specify the PLS-SEM model using cSEM syntax. Define measurement models (e.g., 'eta1 =~ y1 + y2 + y3') and structural model (e.g., 'eta2 ~ eta1').")
content: TextArea { name: "syntax"; width: models.width; textType: JASP.TextTypeCSem; showLineNumber: true }
}
@@ -39,7 +40,7 @@ Form
Section
{
title: qsTr("Model")
-
+ info: qsTr("Model-level settings such as grouping variables for multi-group analysis.")
Group
{
@@ -52,6 +53,7 @@ Form
showVariableTypeIcon: true
addEmptyValue: true
allowedColumns: ["nominal"]
+ info: qsTr("Select a grouping variable to perform multi-group PLS-SEM analysis.")
}
}
}
@@ -59,18 +61,21 @@ Form
Section
{
title: qsTr("Estimation")
+ info: qsTr("Settings for the PLS-SEM estimation algorithm, convergence criteria, and error calculation.")
Group
{
CheckBox
{
name: "consistentPartialLeastSquares"; label: qsTr("Consistent partial least squares"); checked: true
+ info: qsTr("Use consistent PLS (PLSc) to correct for attenuation, producing consistent estimates for common factor models.")
}
DropDown
{
name: "innerWeightingScheme"
label: qsTr("Inner weighting scheme")
id: approachInner
+ info: qsTr("Choose the scheme for estimating inner weights relating constructs to each other.")
values: [
{ value: "path", label: qsTr("Path") },
{ value: "centroid", label: qsTr("Centroid") },
@@ -83,12 +88,14 @@ Form
enabled: approachInner.currentValue != "path"
name: "structuralModelIgnored"
label: qsTr("Ignore structural model")
+ info: qsTr("Estimate the measurement model only, ignoring the structural (inner) model.")
}
DropDown
{
name: "convergenceCriterion"
label: qsTr("Convergence criterion")
+ info: qsTr("Criterion used to assess convergence of the PLS algorithm.")
values: [
{ value: "absoluteDifference", label: qsTr("Absolute difference") },
{ value: "squaredDifference", label: qsTr("Squared difference") },
@@ -103,6 +110,7 @@ Form
fieldWidth: 60
defaultValue: 1e-5
min: 0
+ info: qsTr("Tolerance threshold for the convergence criterion. Smaller values require stricter convergence.")
}
}
@@ -110,13 +118,16 @@ Form
Group
{
title: qsTr("Error calculation method")
+ info: qsTr("Method for computing standard errors and confidence intervals.")
RadioButtonGroup
{
name: "errorCalculationMethod"
id: errorCalcMethod
- RadioButton { value: "none"; label: qsTr("None"); checked: true }
+ info: qsTr("Select the error calculation method.")
+ RadioButton { value: "none"; label: qsTr("None"); checked: true; info: qsTr("Do not compute standard errors or confidence intervals.") }
RadioButton {
value: "bootstrap"; label: qsTr("Bootstrap"); checked: true
+ info: qsTr("Compute standard errors and confidence intervals using bootstrap resampling.")
IntegerField
{
name: "bootstrapSamples"
@@ -124,6 +135,7 @@ Form
fieldWidth: 60
defaultValue: 200
min: 1
+ info: qsTr("Number of bootstrap resamples to draw.")
// enabled: errorCalcMethod.value == "robust"
}
CIField
@@ -131,6 +143,7 @@ Form
text: qsTr("Confidence intervals")
name: "ciLevel"
enabled: errorCalcMethod.value == "bootstrap"
+ info: qsTr("Width of the bootstrap confidence intervals.")
}
}
}
@@ -139,9 +152,10 @@ Form
visible: errorCalcMethod.value != "none"
title: qsTr("Handling of inadmissibles")
name: "handlingOfInadmissibles"
- RadioButton { value: "replace"; label: qsTr("Replace") ; checked: true }
- RadioButton { value: "ignore"; label: qsTr("Ignore") }
- RadioButton { value: "drop"; label: qsTr("Drop") }
+ info: qsTr("How to handle bootstrap samples that produce inadmissible results (e.g., Heywood cases).")
+ RadioButton { value: "replace"; label: qsTr("Replace") ; checked: true; info: qsTr("Replace inadmissible bootstrap samples with new ones.") }
+ RadioButton { value: "ignore"; label: qsTr("Ignore"); info: qsTr("Keep inadmissible results in the bootstrap distribution.") }
+ RadioButton { value: "drop"; label: qsTr("Drop"); info: qsTr("Drop inadmissible bootstrap samples, reducing the effective number of resamples.") }
}
}
@@ -152,41 +166,44 @@ Form
Section
{
title: qsTr("Output")
+ info: qsTr("Additional output tables and statistics to display.")
Group
{
- CheckBox { name: "rSquared"; label: qsTr("R-squared") }
- CheckBox { name: "additionalFitMeasures"; label: qsTr("Additional fit measures") }
- CheckBox { name: "mardiasCoefficient"; label: qsTr("Mardia's coefficient") }
- CheckBox { name: "reliabilityMeasures"; label: qsTr("Reliability measures") }
+ CheckBox { name: "rSquared"; label: qsTr("R-squared"); info: qsTr("Display the proportion of variance explained for each endogenous construct.") }
+ CheckBox { name: "additionalFitMeasures"; label: qsTr("Additional fit measures"); info: qsTr("Display additional fit indices for evaluating model fit.") }
+ CheckBox { name: "mardiasCoefficient"; label: qsTr("Mardia's coefficient"); info: qsTr("Display Mardia's multivariate skewness and kurtosis coefficients to assess multivariate normality.") }
+ CheckBox { name: "reliabilityMeasures"; label: qsTr("Reliability measures"); info: qsTr("Display reliability measures for each construct (e.g., Cronbach's alpha, composite reliability).") }
}
Group
{
- CheckBox { name: "observedIndicatorCorrelation"; label: qsTr("Observed indicator correlations") }
- CheckBox { name: "impliedIndicatorCorrelation"; label: qsTr("Implied indicator correlations") }
- CheckBox { name: "observedConstructCorrelation"; label: qsTr("Observed construct correlations") }
- CheckBox { name: "impliedConstructCorrelation"; label: qsTr("Implied construct correlations") }
+ CheckBox { name: "observedIndicatorCorrelation"; label: qsTr("Observed indicator correlations"); info: qsTr("Display the observed correlation matrix of the indicator variables.") }
+ CheckBox { name: "impliedIndicatorCorrelation"; label: qsTr("Implied indicator correlations"); info: qsTr("Display the model-implied correlation matrix of the indicator variables.") }
+ CheckBox { name: "observedConstructCorrelation"; label: qsTr("Observed construct correlations"); info: qsTr("Display the observed correlation matrix of the constructs.") }
+ CheckBox { name: "impliedConstructCorrelation"; label: qsTr("Implied construct correlations"); info: qsTr("Display the model-implied correlation matrix of the constructs.") }
}
Group
{
- CheckBox { name: "overallModelFit"; label: qsTr("Overall model fit") ; id: omf}
- IntegerField { visible:omf.checked; name: "omfBootstrapSamples"; label: qsTr("Bootstrap samples"); fieldWidth: 60; defaultValue: 499; min: 100 }
- CIField { visible: omf.checked; text: qsTr("Significance level"); name: "omfSignificanceLevel"; defaultValue: 5 }
- CheckBox { visible: omf.checked; name: "saturatedStructuralModel"; label: qsTr("Saturated structural model") }
+ CheckBox { name: "overallModelFit"; label: qsTr("Overall model fit") ; id: omf; info: qsTr("Perform an overall model fit test using bootstrap-based tests.") }
+ IntegerField { visible:omf.checked; name: "omfBootstrapSamples"; label: qsTr("Bootstrap samples"); fieldWidth: 60; defaultValue: 499; min: 100; info: qsTr("Number of bootstrap samples for the overall model fit test.") }
+ CIField { visible: omf.checked; text: qsTr("Significance level"); name: "omfSignificanceLevel"; defaultValue: 5; info: qsTr("Significance level for the overall model fit test.") }
+ CheckBox { visible: omf.checked; name: "saturatedStructuralModel"; label: qsTr("Saturated structural model"); info: qsTr("Use a saturated structural model as a reference for the model fit test.") }
}
CheckBox
{
name: "addConstructScores"
text: qsTr("Add construct scores to data")
+ info: qsTr("Save estimated construct scores as new columns in the dataset.")
}
}
Section
{
title: qsTr("Prediction")
+ info: qsTr("Settings for cross-validated prediction of endogenous indicator scores.")
Group
{
@@ -194,6 +211,7 @@ Form
{ name: "endogenousIndicatorPrediction"
label: qsTr("Predict endogenous indicator scores")
id: prediction
+ info: qsTr("Perform k-fold cross-validation to predict endogenous indicator scores.")
}
IntegerField
@@ -204,6 +222,7 @@ Form
defaultValue: 10
min: 2
enabled: prediction.checked
+ info: qsTr("Number of folds for cross-validation. Higher values increase computation time but reduce bias.")
}
IntegerField
@@ -214,6 +233,7 @@ Form
defaultValue: 10
min: 1
enabled: prediction.checked
+ info: qsTr("Number of times the cross-validation is repeated to reduce variance in the prediction metrics.")
}
RadioButtonGroup
@@ -221,12 +241,13 @@ Form
title: qsTr("Benchmark(s)")
name: "benchmark"
enabled: prediction.checked
- RadioButton { value: "none"; label: qsTr("None") ; checked: true }
- RadioButton { value: "lm"; label: qsTr("Linear model") }
- RadioButton { value: "GSCA"; label: qsTr("GSCA") }
- RadioButton { value: "PCA"; label: qsTr("PCA") }
- RadioButton { value: "MAXVAR"; label: qsTr("MAXVAR") }
- RadioButton { value: "all"; label: qsTr("All") }
+ info: qsTr("Select a benchmark model to compare the prediction accuracy of the PLS-SEM model.")
+ RadioButton { value: "none"; label: qsTr("None") ; checked: true; info: qsTr("No benchmark comparison.") }
+ RadioButton { value: "lm"; label: qsTr("Linear model"); info: qsTr("Compare against a linear regression model.") }
+ RadioButton { value: "GSCA"; label: qsTr("GSCA"); info: qsTr("Compare against Generalized Structured Component Analysis.") }
+ RadioButton { value: "PCA"; label: qsTr("PCA"); info: qsTr("Compare against Principal Component Analysis.") }
+ RadioButton { value: "MAXVAR"; label: qsTr("MAXVAR"); info: qsTr("Compare against the MAXVAR approach.") }
+ RadioButton { value: "all"; label: qsTr("All"); info: qsTr("Compare against all available benchmark models.") }
}
}
}
diff --git a/inst/qml/SEM.qml b/inst/qml/SEM.qml
index fed02133..935c5f96 100644
--- a/inst/qml/SEM.qml
+++ b/inst/qml/SEM.qml
@@ -56,8 +56,9 @@ Form
maximumItems: 9
newItemName: qsTr("Model 1")
optionKey: "name"
+ info: qsTr("Specify the structural equation model using lavaan syntax. Multiple models can be specified and compared. See lavaan.org for syntax tutorials.")
- content: TextArea { name: "syntax"; width: models.width; textType: JASP.TextTypeLavaan; showLineNumber: true }
+ content: TextArea { name: "syntax"; width: models.width; textType: JASP.TextTypeLavaan; showLineNumber: true; info: qsTr("Enter the lavaan model syntax using variable names from the dataset.") }
}
RadioButtonGroup
@@ -65,11 +66,13 @@ Form
title: qsTr("Data")
name: "dataType"
columns: 2
- RadioButton { value: "raw"; label: qsTr("Raw"); checked: true }
+ info: qsTr("Select whether the input is a raw data matrix or a variance-covariance matrix.")
+ RadioButton { value: "raw"; label: qsTr("Raw"); checked: true; info: qsTr("Use raw data with observations as rows and variables in columns.") }
RadioButton
{
value: "varianceCovariance"; label: qsTr("Variance-covariance matrix")
- IntegerField { name: "sampleSize"; label: qsTr("Sample size"); defaultValue: 500 }
+ info: qsTr("Use a variance-covariance matrix as input. Requires specifying the sample size.")
+ IntegerField { name: "sampleSize"; label: qsTr("Sample size"); defaultValue: 500; info: qsTr("The number of observations the covariance matrix is based on.") }
}
}
@@ -79,17 +82,20 @@ Form
label: qsTr("Sampling weights")
showVariableTypeIcon: true
addEmptyValue: true
+ info: qsTr("Select a variable from the dataset to use as sampling weights for each observation.")
}
Section
{
title: qsTr("Model Options")
+ info: qsTr("Options for configuring the structural equation model specification.")
Group
{
DropDown
{
name: "factorScaling"
label: qsTr("Factor scaling")
+ info: qsTr("How the metric of latent variables is determined: by fixing the first loading to 1 (Factor loadings), fixing factor variance to 1 (Factor variance), fixing average loadings to 1 (Effects coding), or none.")
values:
[
{ label: qsTr("Factor loadings"), value: "factorLoading" },
@@ -103,12 +109,13 @@ Form
name: "meanStructure"
label: qsTr("Mean structure")
checked: eq_intercepts.checked || eq_means.checked || eq_thresholds.checked
- CheckBox { name: "latentInterceptFixedToZero"; label: qsTr("Latent means fixed to zero"); checked: !eq_means.checked }
- CheckBox { name: "manifestInterceptFixedToZero"; label: qsTr("Manifest intercepts fixed to zero") }
- CheckBox { name: "manifestMeanFixedToZero"; label: qsTr("Mean of manifest intercepts fixed to zero") }
+ info: qsTr("Estimate observed intercepts and/or latent means. Some elements need to be fixed for identification.")
+ CheckBox { name: "latentInterceptFixedToZero"; label: qsTr("Latent means fixed to zero"); checked: !eq_means.checked; info: qsTr("Fix latent means to zero; observed intercepts are estimated freely.") }
+ CheckBox { name: "manifestInterceptFixedToZero"; label: qsTr("Manifest intercepts fixed to zero"); info: qsTr("Fix observed intercepts to zero; latent means are estimated freely.") }
+ CheckBox { name: "manifestMeanFixedToZero"; label: qsTr("Mean of manifest intercepts fixed to zero"); info: qsTr("Fix the mean of manifest intercepts to zero; latent means are estimated freely.") }
}
- CheckBox { name: "orthogonal"; label: qsTr("Assume factors uncorrelated") }
+ CheckBox { name: "orthogonal"; label: qsTr("Assume factors uncorrelated"); info: qsTr("Estimate factors as orthogonal (uncorrelated) instead of allowing them to correlate.") }
}
Group
@@ -119,6 +126,7 @@ Form
label: qsTr("Exogenous covariate(s) fixed")
id: fix_x
checked: true
+ info: qsTr("If checked, exogenous covariates are considered fixed and their means, variances, and covariances are fixed to sample values.")
}
CheckBox
{
@@ -127,20 +135,22 @@ Form
id: cond_x
// Try to mimic lavaan's default setting for conditional.x
checked: ["wls", "dwls", "wlsm", "wlsmv"].includes(estimator.value) && errorCalc.value != "bootstrap"
+ info: qsTr("Condition on the exogenous covariates when estimating the model.")
}
- CheckBox { name: "residualSingleIndicatorOmitted"; label: qsTr("Residual single indicator omitted"); checked: true }
- CheckBox { name: "residualVariance"; label: qsTr("Residual variances included"); checked: true }
- CheckBox { name: "exogenousLatentCorrelation"; label: qsTr("Exogenous latents correlated"); checked: true }
- CheckBox { name: "dependentCorrelation"; label: qsTr("Dependent variables correlated"); checked: true }
- CheckBox { name: "threshold"; label: qsTr("Thresholds"); checked: true }
- CheckBox { name: "scalingParameter"; label: qsTr("Scaling parameters"); checked: true }
- CheckBox { name: "efaConstrained"; label: qsTr("EFA blocks constrained"); checked: true }
+ CheckBox { name: "residualSingleIndicatorOmitted"; label: qsTr("Residual single indicator omitted"); checked: true; info: qsTr("Set the residual variance of a single indicator to zero if it is the only indicator of a latent variable.") }
+ CheckBox { name: "residualVariance"; label: qsTr("Residual variances included"); checked: true; info: qsTr("Include residual variances of observed and latent variables as free parameters.") }
+ CheckBox { name: "exogenousLatentCorrelation"; label: qsTr("Exogenous latents correlated"); checked: true; info: qsTr("Include covariances of exogenous latent variables in the model.") }
+ CheckBox { name: "dependentCorrelation"; label: qsTr("Dependent variables correlated"); checked: true; info: qsTr("Include covariances of dependent variables (observed and latent) in the model.") }
+ CheckBox { name: "threshold"; label: qsTr("Thresholds"); checked: true; info: qsTr("Include thresholds for limited (non-continuous) dependent variables.") }
+ CheckBox { name: "scalingParameter"; label: qsTr("Scaling parameters"); checked: true; info: qsTr("Include response scaling parameters for limited (non-continuous) dependent variables.") }
+ CheckBox { name: "efaConstrained"; label: qsTr("EFA blocks constrained"); checked: true; info: qsTr("Impose constraints to make exploratory factor analysis blocks identifiable: factor variances set to 1, covariances to zero, and loadings follow an echelon pattern.") }
}
}
Section
{
title: qsTr("Estimation Options")
+ info: qsTr("Options for the estimation method, model test, standard errors, confidence intervals, and missing data handling.")
Group
{
@@ -151,6 +161,7 @@ Form
name: "estimator"
label: qsTr("Estimator")
id: estimator
+ info: qsTr("Choose the estimation method. Some estimators set implicit options for test and standard errors. ML-based extensions: MLM (robust SE, Satorra-Bentler test), MLMV (robust SE, scaled-shifted test), MLMVS (robust SE, Satterthwaite test), MLF (first-order SE), MLR (Huber-White SE, Yuan-Bentler test). WLS variants: WLSM/WLSMV imply DWLS with robust SE, ULSM/ULSMV imply ULS with robust SE.")
values: [
{ value: "default", label: qsTr("Default") },
{ value: "ml", label: qsTr("ML") },
@@ -171,11 +182,6 @@ Form
{ value: "ulsmv", label: qsTr("ULSMV") }
]
}
- HelpButton
- {
- toolTip: qsTr("Click for more information")
- helpPage: "forQml/tooltipEstimators"
- }
}
DropDown
@@ -183,6 +189,7 @@ Form
name: "modelTest"
id: modTest
label: qsTr("Model test")
+ info: qsTr("Choose the test statistic for evaluating model fit. If left at Default, the test is determined by the chosen estimator.")
values: [
{ value: "default", label: qsTr("Default") },
{ value: "standard", label: qsTr("Standard") },
@@ -205,12 +212,14 @@ Form
fieldWidth: 60
defaultValue: 1000
min: 1
+ info: qsTr("Number of bootstrap samples for the Bollen-Stine bootstrap test.")
}
DropDown
{
label: qsTr("Information matrix")
name: "informationMatrix"
+ info: qsTr("Matrix used to compute the standard errors: expected, observed, or first order (outer product of casewise scores).")
values: [
{ value: "default", label: qsTr("Default") },
{ value: "expected", label: qsTr("Expected") },
@@ -224,6 +233,7 @@ Form
label: qsTr("Standard errors")
name: "errorCalculationMethod"
id: errorCalc
+ info: qsTr("Method for computing standard errors. Standard uses the information matrix, Robust uses robust.sem, Robust Huber-White uses the mlr approach, and Bootstrap computes SEs from bootstrapped fits.")
values: [
{ value: "default", label: qsTr("Default") },
{ value: "standard", label: qsTr("Standard") },
@@ -241,12 +251,14 @@ Form
fieldWidth: 60
defaultValue: 1000
min: 1
+ info: qsTr("Number of bootstrap samples to use for computing standard errors.")
}
DropDown {
visible: errorCalc.value == "bootstrap"
label: qsTr(" Type")
name: "bootstrapCiType"
+ info: qsTr("Type of bootstrap confidence interval.")
values: [
{ label: qsTr("Bias-corrected percentile"), value: "percentileBiasCorrected" },
{ label: qsTr("Percentile"), value: "percentile" },
@@ -257,6 +269,7 @@ Form
CIField {
text: qsTr("Confidence intervals")
name: "ciLevel"
+ info: qsTr("Width of the confidence intervals for parameter estimates.")
}
CheckBox
@@ -267,6 +280,7 @@ Form
label: qsTr("Set a random seed:")
checked: false
childrenOnSameRow: true
+ info: qsTr("Set a seed to guarantee reproducible bootstrap results.")
IntegerField
{
@@ -282,12 +296,13 @@ Form
Group
{
id: missingG
- CheckBox{name: "standardizedVariable"; label: qsTr("Standardize variables before estimation"); checked: false}
+ CheckBox{name: "standardizedVariable"; label: qsTr("Standardize variables before estimation"); checked: false; info: qsTr("Z-standardize all variables before estimation.")}
DropDown
{
name: "naAction"
label: qsTr("Missing data handling")
+ info: qsTr("How to treat missing values. FIML uses full-information maximum likelihood. Pairwise computes correlations using available pairs. Two-stage uses EM-estimated statistics. Robust two-stage adds robustness against non-normality. Doubly robust is for PML estimation.")
values: [
{ label: qsTr("(FI)ML"), value: "fiml" },
{ label: qsTr("Listwise deletion"), value: "listwise" },
@@ -303,6 +318,7 @@ Form
{
name: "emulation"
label: qsTr("Mimic")
+ info: qsTr("Emulate the output from different SEM programs.")
values: [
{ value: "lavaan", label: qsTr("Lavaan") },
{ value: "mplus", label: qsTr("Mplus") },
@@ -316,19 +332,20 @@ Form
Section
{
title: qsTr("Output Options")
+ info: qsTr("Options for additional fit measures, parameter estimates, covariance matrices, plots, and modification indices.")
Group
{
- CheckBox { name: "additionalFitMeasures"; label: qsTr("Additional fit measures") }
- CheckBox { name: "rSquared"; label: qsTr("R-squared") }
- CheckBox { name: "ave"; label: qsTr("Average variance extracted (AVE)") }
- CheckBox { name: "htmt"; label: qsTr("Heterotrait-monotrait ratio (HTMT)") }
- CheckBox { name: "reliability"; label: qsTr("Reliability measures") }
- CheckBox { name: "mardiasCoefficient"; label: qsTr("Mardia's coefficient") }
- CheckBox { name: "observedCovariance"; label: qsTr("Observed covariances") }
- CheckBox { name: "impliedCovariance"; label: qsTr("Implied covariances") }
- CheckBox { name: "residualCovariance"; label: qsTr("Residual covariances") }
- CheckBox { name: "standardizedResidual"; label: qsTr("Standardized residuals") }
+ CheckBox { name: "additionalFitMeasures"; label: qsTr("Additional fit measures"); info: qsTr("Display a table with various fit measures including CFI, TLI, RMSEA, SRMR, and information criteria.") }
+ CheckBox { name: "rSquared"; label: qsTr("R-squared"); info: qsTr("Display the explained variance in each dependent variable.") }
+ CheckBox { name: "ave"; label: qsTr("Average variance extracted (AVE)"); info: qsTr("Display the amount of variance captured by a construct relative to measurement error. Used to evaluate convergent validity.") }
+ CheckBox { name: "htmt"; label: qsTr("Heterotrait-monotrait ratio (HTMT)"); info: qsTr("Display the HTMT ratio to assess discriminant validity between constructs.") }
+ CheckBox { name: "reliability"; label: qsTr("Reliability measures"); info: qsTr("Display reliability metrics such as coefficient alpha and composite (omega) reliability per latent variable.") }
+ CheckBox { name: "mardiasCoefficient"; label: qsTr("Mardia's coefficient"); info: qsTr("Display Mardia's multivariate skewness and kurtosis coefficients to assess multivariate normality.") }
+ CheckBox { name: "observedCovariance"; label: qsTr("Observed covariances"); info: qsTr("Display the observed covariance matrix calculated from the data.") }
+ CheckBox { name: "impliedCovariance"; label: qsTr("Implied covariances"); info: qsTr("Display the model-implied covariance matrix based on estimated parameters.") }
+ CheckBox { name: "residualCovariance"; label: qsTr("Residual covariances"); info: qsTr("Display residual covariances (observed minus implied).") }
+ CheckBox { name: "standardizedResidual"; label: qsTr("Standardized residuals"); info: qsTr("Display the standardized residual covariance matrix.") }
}
Group
@@ -336,12 +353,14 @@ Form
CheckBox
{
name: "standardizedEstimate"; label: qsTr("Standardized estimates");
+ info: qsTr("Display standardized parameter estimates.")
RadioButtonGroup
{
name: "standardizedEstimateType"
- RadioButton { value: "all"; label: qsTr("All"); checked: true }
- RadioButton { value: "latents"; label: qsTr("Latents") }
- RadioButton { value: "nox"; label: qsTr("Except exogenous covariates") }
+ info: qsTr("Type of standardization.")
+ RadioButton { value: "all"; label: qsTr("All"); checked: true; info: qsTr("Standardize based on variances of both observed and latent variables.") }
+ RadioButton { value: "latents"; label: qsTr("Latents"); info: qsTr("Standardize based on latent variable variances only.") }
+ RadioButton { value: "nox"; label: qsTr("Except exogenous covariates"); info: qsTr("Standardize based on variances of observed and latent variables, excluding exogenous covariates.") }
}
}
CheckBox
@@ -349,30 +368,36 @@ Form
name: "pathPlot";
text: qsTr("Path diagram");
checked: false
+ info: qsTr("Display a path diagram of the model.")
CheckBox {
name: "pathPlotParameter"
text: qsTr("Show parameter estimates")
checked: false
+ info: qsTr("Display parameter estimates on the path diagram.")
CheckBox {
name: "pathPlotParameterStandardized"
text: qsTr("Standardized")
checked: false
+ info: qsTr("Show standardized estimates on the path diagram.")
}
}
CheckBox {
name: "pathPlotLegend"
text: qsTr("Show legend")
checked: false
+ info: qsTr("Display a legend in the path diagram.")
}
}
CheckBox
{
name: "modificationIndex"
label: qsTr("Modification indices")
+ info: qsTr("Display modification indices showing potential improvements to the model.")
CheckBox
{
name: "modificationIndexHiddenLow"
label: qsTr("Hide low indices")
+ info: qsTr("Hide modification indices below the specified threshold.")
DoubleField
{
name: "modificationIndexThreshold"
@@ -380,6 +405,7 @@ Form
negativeValues: false
decimals: 2
defaultValue: 10
+ info: qsTr("Minimum value for modification indices to be displayed.")
}
}
}
@@ -387,6 +413,7 @@ Form
{
name: "warnings";
label: qsTr("Show warnings")
+ info: qsTr("Display warnings produced by lavaan during estimation.")
}
}
@@ -395,6 +422,7 @@ Form
Section
{
title: qsTr("Multigroup SEM")
+ info: qsTr("Options for fitting the model across multiple groups, with equality constraints on parameters.")
Group
{
@@ -405,21 +433,23 @@ Form
label: qsTr("Grouping Variable")
showVariableTypeIcon: true
addEmptyValue: true
+ info: qsTr("Select a nominal or ordinal variable to fit the model separately for each group.")
}
Group
{
visible: grpvar.value != ""
id: constraints
title: qsTr("Equality Constraints")
- CheckBox { id: eq_loadings; name: "equalLoading"; label: qsTr("Loadings") }
- CheckBox { id: eq_intercepts; name: "equalIntercept"; label: qsTr("Intercepts") }
- CheckBox { id: eq_residuals; name: "equalResidual"; label: qsTr("Residuals") }
- CheckBox { id: eq_residualcovariances; name: "equalResidualCovariance"; label: qsTr("Residual covariances") }
- CheckBox { id: eq_means; name: "equalMean"; label: qsTr("Means") }
- CheckBox { id: eq_thresholds; name: "equalThreshold"; label: qsTr("Thresholds") }
- CheckBox { id: eq_regressions; name: "equalRegression"; label: qsTr("Regressions") }
- CheckBox { id: eq_variances; name: "equalLatentVariance"; label: qsTr("Latent variances") }
- CheckBox { id: eq_lvcovariances; name: "equalLatentCovariance"; label: qsTr("Latent covariances") }
+ info: qsTr("Constrain selected parameters to be equal across all groups.")
+ CheckBox { id: eq_loadings; name: "equalLoading"; label: qsTr("Loadings"); info: qsTr("Constrain factor loadings to be equal across groups.") }
+ CheckBox { id: eq_intercepts; name: "equalIntercept"; label: qsTr("Intercepts"); info: qsTr("Constrain intercepts to be equal across groups.") }
+ CheckBox { id: eq_residuals; name: "equalResidual"; label: qsTr("Residuals"); info: qsTr("Constrain residual variances to be equal across groups.") }
+ CheckBox { id: eq_residualcovariances; name: "equalResidualCovariance"; label: qsTr("Residual covariances"); info: qsTr("Constrain residual covariances to be equal across groups.") }
+ CheckBox { id: eq_means; name: "equalMean"; label: qsTr("Means"); info: qsTr("Constrain means to be equal across groups.") }
+ CheckBox { id: eq_thresholds; name: "equalThreshold"; label: qsTr("Thresholds"); info: qsTr("Constrain thresholds to be equal across groups.") }
+ CheckBox { id: eq_regressions; name: "equalRegression"; label: qsTr("Regressions"); info: qsTr("Constrain regression coefficients to be equal across groups.") }
+ CheckBox { id: eq_variances; name: "equalLatentVariance"; label: qsTr("Latent variances"); info: qsTr("Constrain latent variable variances to be equal across groups.") }
+ CheckBox { id: eq_lvcovariances; name: "equalLatentCovariance"; label: qsTr("Latent covariances"); info: qsTr("Constrain latent variable covariances to be equal across groups.") }
} // No model or source: it takes all variables per default
}
@@ -431,6 +461,7 @@ Form
height: constraints.height + grpvar.height
textType: JASP.TextTypeLavaan
visible: eq_loadings.checked || eq_intercepts.checked || eq_residuals.checked || eq_residualcovariances.checked || eq_means.checked || eq_thresholds.checked || eq_regressions.checked || eq_variances.checked || eq_lvcovariances.checked
+ info: qsTr("Release specific equality constraints using lavaan syntax, e.g., 'f=~x2' to release a single loading.")
}
}
@@ -439,30 +470,35 @@ Form
Section
{
title: qsTr("Sensitivity Analysis")
+ info: qsTr("Conduct sensitivity analysis against a potential missing confounder using phantom variables.")
CheckBox
{
name: "sensitivityAnalysis"
label: qsTr("Run sensitivity analysis")
+ info: qsTr("Run a sensitivity analysis by adding phantom variables (latent variables without indicators) to assess the robustness of the model.")
RadioButtonGroup
{
title: qsTr("Search algorithm")
name: "searchAlgorithm"
id: search
+ info: qsTr("Algorithm for sampling phantom variables.")
RadioButton
{
value: "antColonyOptimization"
label: qsTr("Ant colony optimization")
- checked: true
- IntegerField { name: "numberOfAnts"; label: qsTr("Number of ants"); defaultValue: 10 }
- IntegerField { name: "sizeOfSolutionArchive"; label: qsTr("Size of the solution archive"); defaultValue: 100 }
- DoubleField { name: "convergenceRateThreshold"; label: qsTr("Convergence rate threshold"); defaultValue: 0.1; negativeValues: false }
+ checked: true
+ info: qsTr("Use ant colony optimization to find good paths through the parameter space.")
+ IntegerField { name: "numberOfAnts"; label: qsTr("Number of ants"); defaultValue: 10; info: qsTr("Number of artificial ants per iteration, each representing a potential solution.") }
+ IntegerField { name: "sizeOfSolutionArchive"; label: qsTr("Size of the solution archive"); defaultValue: 100; info: qsTr("Number of best solutions stored during optimization.") }
+ DoubleField { name: "convergenceRateThreshold"; label: qsTr("Convergence rate threshold"); defaultValue: 0.1; negativeValues: false; info: qsTr("If the change in the objective function is smaller than this threshold, the algorithm has converged.") }
}
- RadioButton { value: "tabuSearch"; label: qsTr("Tabu search") }
+ RadioButton { value: "tabuSearch"; label: qsTr("Tabu search"); info: qsTr("Use tabu search, which maintains a list of recently visited solutions to avoid local optima.") }
}
DropDown
{
name: "optimizerFunction"
label: qsTr("Optimizer function")
+ info: qsTr("Objective function maximized during the optimization.")
values:
[
{ label: qsTr("% change mean estimate") , value: "percentChangeMeanEstimate" },
@@ -480,8 +516,9 @@ Form
negativeValues: false
decimals: 4
defaultValue: 0.05
+ info: qsTr("Significance level for the sensitivity analysis.")
}
- IntegerField { name: "maxIterations"; label: qsTr("Maximum number of iterations"); defaultValue: 1000 }
+ IntegerField { name: "maxIterations"; label: qsTr("Maximum number of iterations"); defaultValue: 1000; info: qsTr("Maximum number of iterations for the optimization algorithm.") }
SetSeed{}
}
}
diff --git a/tests/testthat/test-ModeratedNonLinearFactorAnalysis.R b/tests/testthat/test-ModeratedNonLinearFactorAnalysis.R
index dbbe66b6..206dffb5 100644
--- a/tests/testthat/test-ModeratedNonLinearFactorAnalysis.R
+++ b/tests/testthat/test-ModeratedNonLinearFactorAnalysis.R
@@ -408,3 +408,211 @@ if (isMacOS) {
})
}
+
+# Configural invariance with loadings, factor variance/means/covariances, fit per group
+# Uses simplified moderator setup (Age + squared only) for faster convergence (~15s vs ~225s)
+options2 <- options
+options2$invarianceTestConfigural <- TRUE
+options2$invarianceTestScalar <- FALSE
+options2$checkModelFitPerGroup <- TRUE
+options2$parameterEstimatesLoadings <- TRUE
+options2$parameterEstimatesIntercepts <- FALSE
+options2$parameterEstimatesResidualVariances <- FALSE
+options2$parameterEstimatesFactorVariance <- TRUE
+options2$parameterEstimatesFactorMeans <- TRUE
+options2$parameterEstimatesFactorCovariances <- TRUE
+
+# Simplified moderators: Age + squared only (no Male, no interaction)
+options2$moderators <- list(
+ list(variable = "Age", moderatorSquaredEffect = TRUE, moderatorCubicEffect = FALSE)
+)
+options2$moderators.types <- c("scale")
+options2$moderatorInteractionTerms <- list()
+
+# Update individual moderations for configural
+options2$includeIndividualModerationsList <- list(
+ list(
+ keyLabel = "Configural",
+ keyValue = "invarianceTestConfigural",
+ moderationTypeList = list(
+ list(
+ keyLabel = "Indicators",
+ keyValue = "indicators",
+ moderationParameterList = list(
+ list(keyLabel = "Loadings", keyValue = "loadings",
+ moderationItemList = list(
+ list(includeIndividualModeration = TRUE, value = "AgeImportant", value.types = "scale"),
+ list(includeIndividualModeration = TRUE, value = "AttractiveImportant", value.types = "scale"),
+ list(includeIndividualModeration = TRUE, value = "PhysicalbuildImportant", value.types = "scale"),
+ list(includeIndividualModeration = TRUE, value = "TrustImportant", value.types = "scale"),
+ list(includeIndividualModeration = TRUE, value = "EmotionalconnImportant", value.types = "scale"),
+ list(includeIndividualModeration = TRUE, value = "OpennessImportant", value.types = "scale")
+ )),
+ list(keyLabel = "Intercepts", keyValue = "intercepts",
+ moderationItemList = list(
+ list(includeIndividualModeration = TRUE, value = "AgeImportant", value.types = "scale"),
+ list(includeIndividualModeration = TRUE, value = "AttractiveImportant", value.types = "scale"),
+ list(includeIndividualModeration = TRUE, value = "PhysicalbuildImportant", value.types = "scale"),
+ list(includeIndividualModeration = TRUE, value = "TrustImportant", value.types = "scale"),
+ list(includeIndividualModeration = TRUE, value = "EmotionalconnImportant", value.types = "scale"),
+ list(includeIndividualModeration = TRUE, value = "OpennessImportant", value.types = "scale")
+ )),
+ list(keyLabel = "Residual variances", keyValue = "residualVariances",
+ moderationItemList = list(
+ list(includeIndividualModeration = TRUE, value = "AgeImportant", value.types = "scale"),
+ list(includeIndividualModeration = TRUE, value = "AttractiveImportant", value.types = "scale"),
+ list(includeIndividualModeration = TRUE, value = "PhysicalbuildImportant", value.types = "scale"),
+ list(includeIndividualModeration = TRUE, value = "TrustImportant", value.types = "scale"),
+ list(includeIndividualModeration = TRUE, value = "EmotionalconnImportant", value.types = "scale"),
+ list(includeIndividualModeration = TRUE, value = "OpennessImportant", value.types = "scale")
+ ))
+ )
+ ),
+ list(
+ keyLabel = "Factors",
+ keyValue = "factors",
+ moderationParameterList = list(
+ list(keyLabel = "Variances", keyValue = "variances",
+ moderationItemList = list(
+ list(includeIndividualModeration = TRUE, value = "Factor1"),
+ list(includeIndividualModeration = TRUE, value = "Factor2")
+ )),
+ list(keyLabel = "Means", keyValue = "means",
+ moderationItemList = list(
+ list(includeIndividualModeration = TRUE, value = "Factor1"),
+ list(includeIndividualModeration = TRUE, value = "Factor2")
+ )),
+ list(keyLabel = "Covariances", keyValue = "covariances",
+ moderationItemList = list(
+ list(includeIndividualModeration = TRUE, value = "Factor1:Factor2")
+ ))
+ )
+ )
+ )
+ )
+)
+
+# Update plot list for configural
+options2$plotModelList <- list(
+ list(
+ keyLabel = "Configural",
+ keyValue = "invarianceTestConfigural",
+ plotTypeList = list(
+ list(keyLabel = "Indicators", keyValue = "indicators",
+ plotParameterList = list(
+ list(keyLabel = "Loadings", keyValue = "loadings", plotItemList = list()),
+ list(keyLabel = "Intercepts", keyValue = "intercepts", plotItemList = list()),
+ list(keyLabel = "Residual variances", keyValue = "residualVariances", plotItemList = list())
+ )),
+ list(keyLabel = "Factors", keyValue = "factors",
+ plotParameterList = list(
+ list(keyLabel = "Variances", keyValue = "variances",
+ plotItemList = list(
+ list(includePlot = FALSE, plotModerator1 = "", plotModerator2 = "", value = "Factor1"),
+ list(includePlot = FALSE, plotModerator1 = "", plotModerator2 = "", value = "Factor2")
+ )),
+ list(keyLabel = "Means", keyValue = "means",
+ plotItemList = list(
+ list(includePlot = FALSE, plotModerator1 = "", plotModerator2 = "", value = "Factor1"),
+ list(includePlot = FALSE, plotModerator1 = "", plotModerator2 = "", value = "Factor2")
+ )),
+ list(keyLabel = "Covariances", keyValue = "covariances",
+ plotItemList = list(
+ list(includePlot = FALSE, plotModerator1 = "", plotModerator2 = "", value = "Factor1:Factor2")
+ ))
+ ))
+ )
+ )
+)
+
+results2 <- runAnalysis(
+ "ModeratedNonLinearFactorAnalysis",
+ dataset = testthat::test_path("AttractDat.csv"),
+ options = options2, makeTests = FALSE
+)
+
+test_that("Configural invariance fit table results match", {
+ table <- results2[["results"]][["fitContainer"]][["collection"]][["fitContainer_invFitTable"]][["data"]]
+ if (isMacOS) {
+ jaspTools::expect_equal_tables(table,
+ list(110750.546348301, 111196.589369783, 110620.546348301, 65,
+ 110751.773114101, 110990.034281801, "Configural"))
+ } else {
+ expect_true(!is.null(table))
+ }
+})
+
+test_that("Configural loadings table results match", {
+ table <- results2[["results"]][["mainContainer"]][["collection"]][["mainContainer_globalParameterContainer"]][["collection"]][["mainContainer_globalParameterContainer_Configural"]][["collection"]][["mainContainer_globalParameterContainer_Configural_loadTable"]][["data"]]
+ expect_true(!is.null(table))
+ expect_true(length(table) > 0)
+})
+
+test_that("Configural factor variance table results match", {
+ table <- results2[["results"]][["mainContainer"]][["collection"]][["mainContainer_globalParameterContainer"]][["collection"]][["mainContainer_globalParameterContainer_Configural"]][["collection"]][["mainContainer_globalParameterContainer_Configural_fvTable"]][["data"]]
+ if (isMacOS) {
+ jaspTools::expect_equal_tables(table,
+ list(1.08331308523565, 1.65928141774314, "Age", 1.34071670084679,
+ "Factor 1", 0.00702411310741757, 0.145826350898154, 0.511029823553375,
+ 0.785480541670386, "Age_squared", 0.633564505488136, "Factor 1",
+ 3.15729676789722e-05, 0.0694780466327939, 0.178631637186566,
+ 0.66501509918342, "Age", 0.344663221015705, "Factor 2",
+ 0.00149063776278924, 0.115577193480205, 1.07360222788718,
+ 1.34470928899678, "Age_squared", 1.20153355697106, "Factor 2",
+ 0.00139158860273825, 0.0690153588391524))
+ } else {
+ expect_true(!is.null(table))
+ }
+})
+
+test_that("Configural factor means table results match", {
+ table <- results2[["results"]][["mainContainer"]][["collection"]][["mainContainer_globalParameterContainer"]][["collection"]][["mainContainer_globalParameterContainer_Configural"]][["collection"]][["mainContainer_globalParameterContainer_Configural_fmTable"]][["data"]]
+ if (isMacOS) {
+ jaspTools::expect_equal_tables(table,
+ list(-0.11797505313098, 0.0702015237324405, "Age", -0.0238867646992695,
+ "Factor 1", 0.618774499028364, 0.0480051108968667, -0.0520716012405416,
+ 0.143649915681573, "Age_squared", 0.0457891572205155, "Factor 1",
+ 0.35910631756296, 0.0499298758716845, -0.81636702891802,
+ 3.34030668490767, "Age", 1.26196982799482, "Factor 2",
+ 0.234009601602057, 1.06039543241942, -0.41875922337702,
+ 0.152742711494277, "Age_squared", -0.133008255941372, "Factor 2",
+ 0.361609370989496, 0.145793988914906))
+ } else {
+ expect_true(!is.null(table))
+ }
+})
+
+test_that("Configural factor covariances table results match", {
+ table <- results2[["results"]][["mainContainer"]][["collection"]][["mainContainer_globalParameterContainer"]][["collection"]][["mainContainer_globalParameterContainer_Configural"]][["collection"]][["mainContainer_globalParameterContainer_Configural_covTable"]][["data"]]
+ if (isMacOS) {
+ jaspTools::expect_equal_tables(table,
+ list(0.112585558030865, 0.191798849309964, "Baseline", 0.152192203670414,
+ 5.01820807130571e-14, 0.0202078435889444, -0.00594763537821141,
+ 0.0829403488440276, "Age", 0.0384963567329081, 0.0895690404524621,
+ 0.0226759228545463, -0.058200776839228, -0.00901014210274764,
+ "Age_squared", -0.0336054594709878, 0.00740701381776465,
+ 0.0125488618986088))
+ } else {
+ expect_true(!is.null(table))
+ }
+})
+
+test_that("Fit per group table has data", {
+ table <- results2[["results"]][["groupContainer"]][["collection"]][["groupContainer_checkModelFitPerGroupTable"]][["data"]]
+ if (isMacOS) {
+ jaspTools::expect_equal_tables(table,
+ list(3541, 0.962855543637305, 167.949620595439, 8,
+ "Age_nominal_1:Age_squared_nominal_1", 0, 0.0751421557319197,
+ 0.05283866976707, 2397, 0.952922234559455, 160.894167907472, 8,
+ "Age_nominal_2:Age_squared_nominal_1", 0, 0.0892928015988366,
+ 0.0549013968491845, 531, 0.959623320824042, 30.8625752101873, 8,
+ "Age_nominal_1:Age_squared_nominal_2", 0.00014863914358354,
+ 0.073361857591604, 0.0631340931013203, 591, 0.954701825269132,
+ 49.3382567247161, 8, "Age_nominal_2:Age_squared_nominal_2",
+ 5.47570161435473e-08, 0.093505540527225, 0.0502803502483288))
+ } else {
+ expect_true(!is.null(table))
+ expect_true(length(table) > 0)
+ }
+})
+
diff --git a/tests/testthat/test-lgcm.R b/tests/testthat/test-lgcm.R
index 775f5971..0e5349ff 100644
--- a/tests/testthat/test-lgcm.R
+++ b/tests/testthat/test-lgcm.R
@@ -276,3 +276,94 @@ test_that("Residual variances table results match", {
-0.0399776999941945, 0.393824053017031, 0.176923176511418, 0.109883564718275,
0.110665746011916, "y4", 1.59871670220673))
})
+
+
+# Quadratic growth with all optional outputs
+options3 <- options
+options3$quadratic <- TRUE
+options3$additionalFitMeasures <- TRUE
+options3$rSquared <- TRUE
+options3$impliedCovariance <- TRUE
+options3$residualCovariance <- TRUE
+options3$syntax <- TRUE
+options3$curvePlot <- TRUE
+options3$pathPlot <- TRUE
+
+set.seed(1)
+results3 <- jaspTools::runAnalysis("LatentGrowthCurve", testthat::test_path("poldem_grouped.csv"), options3, makeTests = FALSE)
+
+test_that("Quadratic latent curve table has correct structure", {
+ # NOTE: exact values not tested because the quadratic model produces negative variances
+ # and can converge to different local optima across runs
+ table <- results3[["results"]][["modelContainer"]][["collection"]][["modelContainer_partabs"]][["collection"]][["modelContainer_partabs_latcur"]][["data"]]
+ expect_equal(length(table), 6)
+ labels <- sapply(table, function(row) row[["component"]])
+ types <- sapply(table, function(row) row[["param"]])
+ expect_equal(labels, c("Intercept", "Intercept", "Linear slope", "Linear slope", "Quadratic slope", "Quadratic slope"))
+ expect_equal(types, c("Mean", "Variance", "Mean", "Variance", "Mean", "Variance"))
+})
+
+test_that("Additional fit measures table results match", {
+ table <- results3[["results"]][["modelContainer"]][["collection"]][["modelContainer_fitIndices"]][["data"]]
+ jaspTools::expect_equal_tables(table,
+ list("Comparative Fit Index (CFI)", 0.859848311804056, "Tucker-Lewis Index (TLI)",
+ 0.34595878841893, "Bentler-Bonett Non-normed Fit Index (NNFI)",
+ 0.34595878841893, "Bentler-Bonett Normed Fit Index (NFI)", 0.854314001958123,
+ "Parsimony Normed Fit Index (PNFI)", 0.183067286133883, "Bollen's Relative Fit Index (RFI)",
+ 0.320132009137905, "Bollen's Incremental Fit Index (IFI)", 0.868202657710421,
+ "Relative Noncentrality Index (RNI)", 0.859848311804056, "Root mean square error of approximation (RMSEA)",
+ 0.328776940788045, "RMSEA 90% CI lower bound", 0.222855445658039,
+ "RMSEA 90% CI upper bound", 0.44682992305614, "RMSEA p-value",
+ 2.74098924707422e-05, "Standardized root mean square residual (SRMR)",
+ 0.110884553767486, "Hoelter's critical N (\u03B1 = .05)",
+ 22.4523640739803, "Hoelter's critical N (\u03B1 = .01)",
+ 32.1430179628636, "Goodness of fit index (GFI)", 0.951665034033744,
+ "McDonald fit index (MFI)", 0.850320947738198, "Expected cross validation index (ECVI)",
+ 0.870949497048504, "Log-likelihood", -698.619539754982, "Number of free parameters",
+ 19, "Akaike (AIC)", 1435.23907950996, "Bayesian (BIC)", 1479.27135366715,
+ "Sample-size adjusted Bayesian (SSABIC)", 1419.38835974857))
+})
+
+test_that("R-squared table results match", {
+ table <- results3[["results"]][["modelContainer"]][["collection"]][["modelContainer_rsquared"]][["data"]]
+ jaspTools::expect_equal_tables(table,
+ list("y1", "", "y2", 0.167939386500449, "y3", 0.392059398679358, "y4",
+ -0.606294027492821))
+})
+
+test_that("Implied covariance table results match", {
+ table <- results3[["results"]][["modelContainer"]][["collection"]][["modelContainer_impliedCovTab"]][["data"]]
+ jaspTools::expect_equal_tables(table,
+ list("", "", 6.78632108886267, "", "", "", "", "", 6.13538851199859,
+ 17.7312477719085, "", "", "", "", 5.7745274807624, 4.38177197317977,
+ 11.3956331777628, "", "", "", 5.99378295934392, 10.3473798134326,
+ 6.03250683495574, 11.4644638754404, "", 1.949678538072, 0.897531861127889,
+ 0.884161212109168, 1.15203565891163, 1.70115520153528, 0.249955555555555,
+ -0.189515866666667, -0.238678218688687, 0.0210765120842407,
+ -0.0530634658926051, -0.461098152619225))
+})
+
+test_that("Residual covariance table results match", {
+ table <- results3[["results"]][["modelContainer"]][["collection"]][["modelContainer_rescov"]][["data"]]
+ jaspTools::expect_equal_tables(table,
+ list("", "", 0.000530466692885589, "", "", "", "", "", 0.0326268136014054,
+ -2.35915615117634, "", "", "", "", -0.0135416022735049, 1.3790085248548,
+ -0.77490174609429, "", "", "", 0.0136802746294089, -0.965600705346711,
+ 0.56626174174086, -0.395111315001229, "", 0, 0.0017693188721104,
+ 0.270054316946833, -0.126811462707632, 0.112360610585651, 0,
+ 0, 0.000580440910909863, 0.0885472692490925, -0.0415792772185059,
+ 0.0368416571525587))
+})
+
+test_that("Model syntax is shown", {
+ syntax <- results3[["results"]][["modelContainer"]][["collection"]][["modelContainer_model_syntax"]]
+ expect_true(!is.null(syntax))
+})
+
+test_that("Curve plot is created", {
+ expect_true(!is.null(results3[["results"]][["modelContainer"]][["collection"]][["modelContainer_curveplot"]][["data"]]))
+})
+
+test_that("Path plot is created", {
+ expect_true(!is.null(results3[["results"]][["modelContainer"]][["collection"]][["modelContainer_pathplot"]][["data"]]))
+})
diff --git a/tests/testthat/test-mediationanalysis.R b/tests/testthat/test-mediationanalysis.R
index 38e1fc46..cd7609fd 100644
--- a/tests/testthat/test-mediationanalysis.R
+++ b/tests/testthat/test-mediationanalysis.R
@@ -279,3 +279,36 @@ test_that("Total effects table results match", {
"", 0.0999482490400043, "contNormal", 0.0978855272669042,
1.64510456659475))
})
+
+
+# R-squared, path plot, syntax
+test_that("R-squared, path plot, and syntax work", {
+ options <- jaspTools::analysisOptions("MediationAnalysis")
+ options$predictors <- "contcor1"
+ options$mediators <- "contcor2"
+ options$outcomes <- "contNormal"
+ options$emulation <- "lavaan"
+ options$estimator <- "ml"
+ options$errorCalculationMethod <- "standard"
+ options$ciLevel <- 0.95
+ options$naAction <- "fiml"
+ options$rSquared <- TRUE
+ options$pathPlot <- TRUE
+ options$syntax <- TRUE
+
+ set.seed(1)
+ results <- jaspTools::runAnalysis("MediationAnalysis", "test.csv", options, makeTests = FALSE)
+
+ # R-squared table
+ table <- results[["results"]][["modelContainer"]][["collection"]][["modelContainer_rsquared"]][["data"]]
+ jaspTools::expect_equal_tables(table,
+ list("contNormal", 0.0355299165169844, "contcor2", 0.431662223819312))
+
+ # Path plot
+ expect_true(!is.null(results[["results"]][["modelContainer"]][["collection"]][["modelContainer_plot"]][["data"]]))
+
+ # Model syntax
+ syntax <- results[["results"]][["modelContainer"]][["collection"]][["modelContainer_syntax"]]
+ expect_true(!is.null(syntax))
+ expect_equal(syntax[["title"]], "Model syntax")
+})
diff --git a/tests/testthat/test-mimic.R b/tests/testthat/test-mimic.R
index 11ce2da4..337ceeaf 100644
--- a/tests/testthat/test-mimic.R
+++ b/tests/testthat/test-mimic.R
@@ -78,3 +78,53 @@ test_that("Indicator coefficients table results match", {
0.865933901606924, 0.75899826211313, 0, "y6", 0.0545600022945775,
13.911257884763))
})
+
+
+# Additional fit measures, R-squared, path plot, syntax
+options2 <- options
+options2$additionalFitMeasures <- TRUE
+options2$rSquared <- TRUE
+options2$pathPlot <- TRUE
+options2$syntax <- TRUE
+
+set.seed(1)
+results2 <- jaspTools::runAnalysis("MIMIC", testthat::test_path("poldem_grouped.csv"), options2, makeTests = FALSE)
+
+test_that("Additional fit measures table results match", {
+ table <- results2[["results"]][["modelContainer"]][["collection"]][["modelContainer_fitIndices"]][["data"]]
+ jaspTools::expect_equal_tables(table,
+ list("Comparative Fit Index (CFI)", 0.90608918395797, "Tucker-Lewis Index (TLI)",
+ 0.870872627942209, "Bentler-Bonett Non-normed Fit Index (NNFI)",
+ 0.870872627942209, "Bentler-Bonett Normed Fit Index (NFI)",
+ 0.844439299152939, "Parsimony Normed Fit Index (PNFI)", 0.614137672111228,
+ "Bollen's Relative Fit Index (RFI)", 0.786104036335291, "Bollen's Incremental Fit Index (IFI)",
+ 0.908772124643973, "Relative Noncentrality Index (RNI)", 0.90608918395797,
+ "Root mean square error of approximation (RMSEA)", 0.126357508478154,
+ "RMSEA 90% CI lower bound", 0.079926210051774, "RMSEA 90% CI upper bound",
+ 0.17273936397227, "RMSEA p-value", 0.00617362342636585, "Standardized root mean square residual (SRMR)",
+ 0.0656147157724176, "Hoelter's critical N (\u03B1 = .05)",
+ 52.7855285925758, "Hoelter's critical N (\u03B1 = .01)",
+ 62.1212676826463, "Goodness of fit index (GFI)", 0.815106974640689,
+ "McDonald fit index (MFI)", 0.825641483206126, "Expected cross validation index (ECVI)",
+ 1.10318927877137, "Log-likelihood", -1010.62207609676, "Number of free parameters",
+ 15, "Akaike (AIC)", 2051.24415219353, "Bayesian (BIC)", 2086.00647389657,
+ "Sample-size adjusted Bayesian (SSABIC)", 2038.73042606611))
+})
+
+test_that("R-squared table results match", {
+ table <- results2[["results"]][["modelContainer"]][["collection"]][["modelContainer_rsquared"]][["data"]]
+ jaspTools::expect_equal_tables(table,
+ list("y1", 0.733658985147143, "y2", 0.567299438689261, "y3", 0.488886066279514,
+ "y4", 0.727826357473676, "y5", 0.645543577276531, "y6", 0.576078361890751,
+ "Y", 0.252668653756736))
+})
+
+test_that("Path plot is created", {
+ expect_true(!is.null(results2[["results"]][["modelContainer"]][["collection"]][["modelContainer_plot"]][["data"]]))
+})
+
+test_that("Model syntax is shown", {
+ syntax <- results2[["results"]][["modelContainer"]][["collection"]][["modelContainer_syntax"]]
+ expect_true(!is.null(syntax))
+ expect_equal(syntax[["title"]], "Model syntax")
+})
diff --git a/tests/testthat/test-plssem.R b/tests/testthat/test-plssem.R
index b04f48e3..d71147b7 100644
--- a/tests/testthat/test-plssem.R
+++ b/tests/testthat/test-plssem.R
@@ -571,3 +571,43 @@ test_that("R-Squared table results match", {
"VAL", 0.758514799820926, 0.762394080145088, "SAT", 0.583411462155354,
0.586757554828805, "LOY"))
})
+
+
+# Endogenous indicator prediction
+test_that("Endogenous indicator prediction works", {
+ # cSEM::predict() uses the future package which may fail if this option is unset
+ oldOpt <- getOption("future.globals.method.default")
+ options("future.globals.method.default" = "ordered")
+ on.exit(options("future.globals.method.default" = oldOpt), add = TRUE)
+
+ options <- jaspTools::analysisOptions("PLSSEM")
+ model <- "
+ ind60 =~ x1 + x2 + x3
+ dem60 =~ y1 + y2 + y3 + y4
+ dem65 =~ y5 + y6 + y7 + y8
+ dem60 ~ ind60
+ dem65 ~ ind60 + dem60
+ "
+ options$models <- list(list(name = "Model1", syntax = list(model = model, columns = c("x1", "x2", "x3", "y1", "y2", "y3", "y4", "y5", "y6", "y7", "y8"))))
+ options$group <- ""
+ options$innerWeightingScheme <- "path"
+ options$convergenceCriterion <- "absoluteDifference"
+ options$setSeed <- TRUE
+ options$seed <- 123
+ options$endogenousIndicatorPrediction <- TRUE
+ options$kFolds <- 5
+ options$repetitions <- 3
+ options$benchmark <- "lm"
+
+ set.seed(1)
+ results <- jaspTools::runAnalysis("PLSSEM", testthat::test_path("poldem_grouped.csv"), options, makeTests = FALSE)
+
+ table <- results[["results"]][["modelContainer"]][["collection"]][["modelContainer_predict"]][["collection"]][["modelContainer_predict_metrics"]][["data"]]
+ # k-fold cross-validation is stochastic; test structure and reasonableness
+ expect_equal(length(table), 8)
+ indicators <- sapply(table, function(row) row[["indicator"]])
+ expect_equal(indicators, c("y1", "y2", "y3", "y4", "y5", "y6", "y7", "y8"))
+ # All Q² predict values should be present and numeric
+ qSquares <- sapply(table, function(row) row[["q2"]])
+ expect_true(all(is.numeric(qSquares)))
+})
diff --git a/tests/testthat/test-sem.R b/tests/testthat/test-sem.R
index b1d24b03..5a9f8703 100644
--- a/tests/testthat/test-sem.R
+++ b/tests/testthat/test-sem.R
@@ -766,9 +766,9 @@ results <- jaspTools::runAnalysis("SEM", data, options, makeTests = FALSE)
test_that("Model fit table results match", {
table <- results[["results"]][["modelContainer"]][["collection"]][["modelContainer_fittab"]][["data"]]
jaspTools::expect_equal_tables(table,
- list(707.570148255052, 721.47507693627, 3.33066907387547e-14, 0, "Model1",
- 75, "", "", "", "", 6, 6, 1095.63355300897, 1109.53848169019,
- 0, 0, "Model2", 75, "", "", 0, 0, 6, 6))
+ list(709.023697474126, 722.928626155344, 0, 0, "Model1", 75, "",
+ "", "", "", 6, 6, 816.268480294992, 830.17340897621,
+ 2.33146835171283e-13, 0, "Model2", 75, "", "", 0, 0, 6, 6))
})
@@ -1069,3 +1069,103 @@ test_that("Summary of sensitivity parameters table results match", {
2.16041463170958, 0.508721525156672, -1.30877622339889, "ind60~phantom"
))
})
+
+
+# Multigroup SEM with loading, intercept, regression, and latent covariance equality constraints
+options <- jaspTools::analysisOptions("SEM")
+options$emulation <- "lavaan"
+options$estimator <- "default"
+options$group <- "group"
+options$informationMatrix <- "expected"
+options$naAction <- "listwise"
+options$modelTest <- "default"
+options$samplingWeights <- ""
+options$equalLoading <- TRUE
+options$equalIntercept <- TRUE
+options$equalRegression <- TRUE
+options$equalLatentCovariance <- TRUE
+
+modelDefault <- list(model = "
+ ind60 =~ x1 + x2 + x3
+ dem60 =~ y1 + y2 + y3 + y4
+ dem65 =~ y5 + y6 + y7 + y8
+ dem60 ~ ind60
+ dem65 ~ ind60 + dem60
+ y1 ~~ y5
+ y2 ~~ y4 + y6
+ y3 ~~ y7
+ y4 ~~ y8
+ y6 ~~ y8
+ ", columns = c("x1", "x2", "x3", "y1", "y2", "y3", "y4", "y5", "y6", "y7", "y8"))
+
+options$models <- list(list(name = "default", syntax = modelDefault))
+
+set.seed(1)
+resultsEq <- jaspTools::runAnalysis("SEM", testthat::test_path("poldem_grouped.csv"), options)
+
+test_that("Equality constraints: fit table results match", {
+ table <- resultsEq[["results"]][["modelContainer"]][["collection"]][["modelContainer_fittab"]][["data"]]
+ jaspTools::expect_equal_tables(table,
+ list(3195.93727697042, 3360.4789330315, 114.87362414236, 83, "default",
+ 75, 0.0117955656694783, "all", 71, 90, 1662.72247217319, 1807.70508431117,
+ 61.4206634603702, 83, "default", 37, 0.963595682697612, 1, 71,
+ 90, 1751.21480479723, 1898.5975591726, 53.4529606819896, 83,
+ "default", 38, 0.995169555905977, 2, 71, 90))
+})
+
+test_that("Equality constraints: factor loadings show equality labels", {
+ table <- resultsEq[["results"]][["modelContainer"]][["collection"]][["modelContainer_params"]][["collection"]][["modelContainer_params_ind"]][["data"]]
+ jaspTools::expect_equal_tables(table,
+ list(1, 1, 1, 1, "", "dem60", "", "y1", 0, "", 0.897879576368359, 1.59841605568629,
+ 1.24814781602732, 1, ".p5.", "dem60", 2.86592971576738e-12,
+ "y2", 0.178711569407314, 6.98414669048418, 0.720039579983597,
+ 1.3056696462548, 1.0128546131192, 1, ".p6.", "dem60", 1.20539134229602e-11,
+ "y3", 0.149398170295622, 6.77956504497351, 0.963777357648586,
+ 1.49779103932152, 1.23078419848505, 1, ".p7.", "dem60", 0, "y4",
+ 0.136230483285704, 9.03457265070284, 1, 1, 1, 1, "", "dem65",
+ "", "y5", 0, "", 0.902973167537218, 1.56404455268417, 1.23350886011069,
+ 1, ".p9.", "dem65", 2.58681964737661e-13, "y6", 0.168643758344898,
+ 7.31428706414389, 0.972281846372528, 1.60283034977338, 1.28755609807296,
+ 1, ".p10.", "dem65", 1.11022302462516e-15, "y7", 0.160857165839408,
+ 8.00434404867227, 1.02208630193642, 1.64022919194269, 1.33115774693955,
+ 1, ".p11.", "dem65", 0, "y8", 0.157692410391747, 8.44148265368401,
+ 1, 1, 1, 1, "", "ind60", "", "x1", 0, "", 1.91703146863215,
+ 2.39706687853372, 2.15704917358293, 1, ".p2.", "ind60", 0, "x2",
+ 0.122460262966062, 17.6142784715457, 1.53079176026025, 2.10831891863736,
+ 1.8195553394488, 1, ".p3.", "ind60", 0, "x3", 0.14733106397173,
+ 12.3501133460758, 1, 1, 1, 2, "", "dem60", "", "y1", 0, "",
+ 0.897879576368359, 1.59841605568629, 1.24814781602732, 2, ".p5.",
+ "dem60", 2.86592971576738e-12, "y2", 0.178711569407314, 6.98414669048418,
+ 0.720039579983597, 1.3056696462548, 1.0128546131192, 2, ".p6.",
+ "dem60", 1.20539134229602e-11, "y3", 0.149398170295622, 6.77956504497351,
+ 0.963777357648587, 1.49779103932152, 1.23078419848505, 2, ".p7.",
+ "dem60", 0, "y4", 0.136230483285704, 9.03457265070285, 1, 1,
+ 1, 2, "", "dem65", "", "y5", 0, "", 0.902973167537218, 1.56404455268417,
+ 1.23350886011069, 2, ".p9.", "dem65", 2.58681964737661e-13,
+ "y6", 0.168643758344898, 7.31428706414389, 0.972281846372528,
+ 1.60283034977338, 1.28755609807296, 2, ".p10.", "dem65", 1.11022302462516e-15,
+ "y7", 0.160857165839408, 8.00434404867226, 1.02208630193642,
+ 1.64022919194269, 1.33115774693955, 2, ".p11.", "dem65", 0,
+ "y8", 0.157692410391747, 8.44148265368401, 1, 1, 1, 2, "", "ind60",
+ "", "x1", 0, "", 1.91703146863215, 2.39706687853372, 2.15704917358293,
+ 2, ".p2.", "ind60", 0, "x2", 0.122460262966062, 17.6142784715458,
+ 1.53079176026025, 2.10831891863736, 1.81955533944881, 2, ".p3.",
+ "ind60", 0, "x3", 0.14733106397173, 12.3501133460758))
+})
+
+test_that("Equality constraints: regression coefficients match", {
+ table <- resultsEq[["results"]][["modelContainer"]][["collection"]][["modelContainer_params"]][["collection"]][["modelContainer_params_reg"]][["data"]]
+ jaspTools::expect_equal_tables(table,
+ list(0.766548188098086, 2.79249963457717, 1.77952391133763, 1, "dem60",
+ 0.000575031911574042, "ind60", 0.516833845534799, 3.44312572930716,
+ 0.291675135601127, 1.55887991282136, 0.925277524211244, 1, "dem65",
+ 0.00420682283183993, "ind60", 0.323272465008486, 2.86222188514248,
+ 0.50155451140844, 0.985099832004553, 0.743327171706497, 1, "dem65",
+ 1.68185709803481e-09, "dem60", 0.123355664800541, 6.025885985118,
+ -0.235581376028428, 2.25465383218978, 1.00953622808068, 2, "dem60",
+ 0.112030881080313, "ind60", 0.63527575707025, 1.58913073078128,
+ -0.00799878409453547, 1.09511856837494, 0.543559892140204, 2,
+ "dem65", 0.0534162703472112, "ind60", 0.281412658898512, 1.9315403019458,
+ 0.651450397707888, 1.08137847142308, 0.866414434565485, 2, "dem65",
+ 2.88657986402541e-15, "dem60", 0.109677544359593, 7.89965201741592))
+})