Skip to content

Commit

Permalink
more estimators for cfa, change standardization output
Browse files Browse the repository at this point in the history
  • Loading branch information
juliuspfadt committed Oct 14, 2024
1 parent 2aac174 commit dff0f98
Show file tree
Hide file tree
Showing 6 changed files with 255 additions and 167 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Package: jaspFactor
Type: Package
Title: Factor Module for JASP
Version: 0.19.0
Date: 2023-04-14
Date: 2024-08-19
Author: JASP Team
Website: jasp-stats.org
Maintainer: JASP Team <[email protected]>
Expand Down
211 changes: 129 additions & 82 deletions R/confirmatoryfactoranalysis.R

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion inst/help/ConfirmatoryFactorAnalysis.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ JASP allows the factors in turn to be indicators of a second-order factor. This
### Advanced
-------
- Emulation: Emulate results from different software
- Error calculation: Change how standard errors for the parameters are computed
- Error calculation: Change how standard errors for the parameters are computed, if bootstrap the CIs are percentile bootstrap type
- Estimator: change the estimator for the CFA (Auto: ML if only scale variables used, WLS otherwise)
- Standardization: display standardized parameters for different standardization schemes
- Missing data handling: change the missing data handling method.
Expand Down
21 changes: 21 additions & 0 deletions inst/help/forQml/tooltipEstimators.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

### Help on Estimators
Some of the estimators come with options that are set in the background:

- Estimators without extra effects (standard errors and model test are standard):
- 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 "Standard errors" instead of leaving it at default the corresponding options set by the estimators in the background will be overwritten
112 changes: 68 additions & 44 deletions inst/qml/ConfirmatoryFactorAnalysis.qml
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ Form
label: qsTr("Model identification")
name: "modelIdentification"
values: [
{ label: qsTr("Factor variances"), value: "factorVariance" },
{ label: qsTr("Marker variable"), value: "markerVariable" },
{ label: qsTr("Factor variances"), value: "factorVariance" },
{ label: qsTr("Effects coding"), value: "effectsCoding" }
]
}
Expand Down Expand Up @@ -206,64 +206,88 @@ Form
Section
{
title: qsTr("Advanced")
RadioButtonGroup
{
title: qsTr("Mimic package")
name: "packageMimiced"
RadioButton { label: qsTr("Lavaan"); value: "lavaan" ; checked: true }
RadioButton { label: qsTr("Mplus") ; value: "Mplus" }
RadioButton { label: qsTr("EQS") ; value: "EQS" }
}

Group
{
title: qsTr("Error calculation")
CIField { text: qsTr("CI level"); name: "ciLevel" }
RadioButtonGroup
Group {
DropDown
{
title: qsTr("Standard error")
name: "seType"
RadioButton { label: qsTr("Standard"); value: "standard"; checked: true}
RadioButton { label: qsTr("Robust"); value: "robust" }
RadioButton {
label: qsTr("Bootstrap")
value: "bootstrap"
IntegerField {
label: qsTr("Bootstrap samples")
name: "bootstrapSamples"
defaultValue: 1000
min: 100
max: 1000000
}
name: "packageMimiced"
label: qsTr("Mimic")
values: [
{ label: qsTr("Lavaan"), value: "lavaan" },
{ label: qsTr("Mplus"), value: "mplus" },
{ label: qsTr("EQS"), value: "eqs" }
]
}
RowLayout
{
DropDown
{
name: "estimator"
label: qsTr("Estimator")
id: estimator
values: [
{ label: qsTr("Default"), value: "default" },
{ label: qsTr("ML"), value: "ml" },
{ label: qsTr("GLS"), value: "gls" },
{ label: qsTr("WLS"), value: "wls" },
{ label: qsTr("ULS"), value: "uls" },
{ label: qsTr("DWLS"), value: "dwls" },
{ label: qsTr("DLS"), value: "dls" },
{ label: qsTr("PML"), value: "pml" },
{ label: qsTr("MLM"), value: "mlm" },
{ label: qsTr("MLMV"), value: "mlmv" },
{ label: qsTr("MLMVS"), value: "mlmvs" },
{ label: qsTr("MLF"), value: "mlf" },
{ label: qsTr("MLR"), value: "mlr" },
{ label: qsTr("WLSM"), value: "wlsm" },
{ label: qsTr("WLSMV"), value: "wlsmv" },
{ label: qsTr("ULSM"), value: "ulsm" },
{ label: qsTr("ULSMV"), value: "ulsmv" }
]
}
HelpButton
{
toolTip: qsTr("Click for more information")
helpPage: "forQml/tooltipEstimators"
}
}
}

RadioButtonGroup
{
title: qsTr("Estimator")
name: "estimator"
RadioButton { label: qsTr("Auto") ; value: "default"; checked: true }
RadioButton { label: qsTr("ML") ; value: "maximumLikelihood" }
RadioButton { label: qsTr("GLS") ; value: "generalizedLeastSquares" }
RadioButton { label: qsTr("WLS") ; value: "weightedLeastSquares" }
RadioButton { label: qsTr("ULS") ; value: "unweightedLeastSquares" }
RadioButton { label: qsTr("DWLS") ; value: "diagonallyWeightedLeastSquares" }
}

DropDown
DropDown
{
label: qsTr("Standard errors")
name: "seType"
id: errorCalc
values: [
{ label: qsTr("Default"), value: "default" },
{ label: qsTr("Standard"), value: "standard" },
{ label: qsTr("Robust"), value: "robust" },
{ label: qsTr("Bootstrap"), value: "bootstrap" }
]
}
IntegerField
{
visible: errorCalc.value == "bootstrap"
name: "bootstrapSamples"
label: qsTr(" Bootstrap samples")
defaultValue: 1000
min: 100
max: 1000000
}
CIField { text: qsTr(" CI level"); name: "ciLevel" }

DropDown
{
name: "naAction"
label: qsTr("Missing data handling")
values:
[
{ label: qsTr("FIML") , value: "fiml" },
{ label: qsTr("Listwise deletion") , value: "listwise" },
{ label: qsTr("FIML") , value: "fiml" },
{ label: qsTr("Pairwise") , value: "pairwise" },
{ label: qsTr("Two-stage") , value: "twoStage" },
{ label: qsTr("Robust two-stage") , value: "twoStageRobust" },
]
}
}

RadioButtonGroup
{
Expand Down
74 changes: 35 additions & 39 deletions tests/testthat/test-confirmatoryfactoranalysis.R
Original file line number Diff line number Diff line change
Expand Up @@ -201,48 +201,44 @@ test_that("[CFA Second order] Chi-square test table results match", {
})


test_that("Bootstrapping works", {
options <- jaspTools::analysisOptions("confirmatoryFactorAnalysis")
options$group <- ""
options$invarianceTesting <- "configural"
options$packageMimiced <- "lavaan"
options$seType <- "bootstrap"
options$bootstrapSamples <- 100
options$estimator <- "default"
options$standardized <- "none"
options$factors <- list(
list(indicators = list("x1", "x2", "x3"), name = "Factor1", title = "Factor 1", types = rep("scale", 3)),
list(indicators = list("x4", "x5", "x6"), name = "Factor2", title = "Factor 2", types = rep("scale", 3)),
list(indicators = list("x7", "x8", "x9"), name = "Factor3", title = "Factor 3", types = rep("scale", 3))
)
options$modelIdentification <- "factorVariance"
options$naAction <- "listwise"
set.seed(1)
results <- jaspTools::runAnalysis("confirmatoryFactorAnalysis", "holzingerswineford.csv", options)
# factor loadings with bootstrapping are correct
options <- jaspTools::analysisOptions("confirmatoryFactorAnalysis")
options$group <- ""
options$invarianceTesting <- "configural"
options$packageMimiced <- "lavaan"
options$seType <- "bootstrap"
options$bootstrapSamples <- 100
options$estimator <- "default"
options$standardized <- "none"
options$factors <- list(
list(indicators = list("x1", "x2", "x3"), name = "Factor1", title = "Factor 1", types = rep("scale", 3)),
list(indicators = list("x4", "x5", "x6"), name = "Factor2", title = "Factor 2", types = rep("scale", 3)),
list(indicators = list("x7", "x8", "x9"), name = "Factor3", title = "Factor 3", types = rep("scale", 3))
)
options$modelIdentification <- "factorVariance"
options$naAction <- "listwise"
set.seed(1)
results <- jaspTools::runAnalysis("confirmatoryFactorAnalysis", "holzingerswineford.csv", options)

test_that("Factor loadings table results match", {
table <- results[["results"]][["estimates"]][["collection"]][["estimates_fl1"]][["data"]]
jaspTools::expect_equal_tables(table,
list(0.712022271311838, 1.11279383173753, 0.899620313867488,
"Factor 1", 0, "x1", 0.0808465333987386, 11.1275063512065, 0.339182433474584,
0.693156723678194, 0.49794051110941, "Factor 1",
1.28623778294923e-10, "x2", 0.0774547818506273, 6.42878979466621,
0.539990088382033, 0.805660643384033, 0.656156092628451,
"Factor 1", 0, "x3", 0.0744212256974568, 8.81678696472846, 0.856032790026098,
1.08543684864592, 0.989693449094392, "Factor 2",
0, "x4", 0.0566367179185465, 17.4744138690689, 0.954112872546464,
1.24054019999221, 1.10160465003145, "Factor 2",
0, "x5", 0.0626757561168699, 17.5762482701815, 0.803928010900409,
1.03630968014001, 0.916600977759373, "Factor 2",
0, "x6", 0.0536584940344529, 17.0821226769958, 0.375767927218761,
0.741040160352204, 0.619475433557926, "Factor 3",
0, "x7", 0.0695825769015842, 8.90273774186456, 0.506218568773711,
0.900974372672674, 0.730948802915075, "Factor 3",
0, "x8", 0.0659093164600047, 11.0902197469857, 0.498364732719689,
0.860170344673322, 0.669980108781259, "Factor 3",
0, "x9", 0.0650169734598685, 10.3046954222623))



list(0.712022271311838, 1.11279383173753, 0.899620313867488, "Factor 1",
0, "x1", 0.101880932132255, 8.8301146744482, 0.339182433474583,
0.693156723678194, 0.49794051110941, "Factor 1", 5.03185138001072e-09,
"x2", 0.0851745954124038, 5.84611536689373, 0.539990088382032,
0.805660643384033, 0.656156092628451, "Factor 1", 0, "x3", 0.0702283472359389,
9.34318004699771, 0.856032790026097, 1.08543684864592, 0.989693449094393,
"Factor 2", 0, "x4", 0.060824826209009, 16.2712088266979, 0.954112872546464,
1.24054019999221, 1.10160465003145, "Factor 2", 0, "x5", 0.0610564023902934,
18.042410081577, 0.803928010900409, 1.03630968014001, 0.916600977759372,
"Factor 2", 0, "x6", 0.0544830064226891, 16.8236123140528, 0.37576792721876,
0.741040160352204, 0.619475433557926, "Factor 3", 7.69848629289527e-11,
"x7", 0.0952105063825611, 6.50637683901018, 0.50621856877371,
0.900974372672673, 0.730948802915075, "Factor 3", 2.32125429988628e-12,
"x8", 0.104217630469302, 7.0136770489172, 0.498364732719688,
0.860170344673323, 0.669980108781259, "Factor 3", 5.52868861802835e-12,
"x9", 0.0972211926575642, 6.8912969535468))
})


Expand Down

0 comments on commit dff0f98

Please sign in to comment.