Description

This shows the output of Structural Equation Modeling (SEM) and Confirmatory Factor Analysis (CFA) functions from the package rwf. The functions include a path diagram plotter that does not need semPlot, a full CFA report (fit indices, parameter estimates, modification indices, predicted scores), and a sample-size planning simulation that tracks how model fit changes as sample size grows.

Installation instructions for rwf can be found here

The code can be found here

Theoretical Background

Confirmatory Factor Analysis

CFA specifies, in advance, which observed indicators load onto which latent factors (unlike EFA, which discovers the structure). For a single-indicator relationship,

\[x_i = \lambda_i \eta + \epsilon_i\]

where \(\eta\) is the latent factor, \(\lambda_i\) is the factor loading (how strongly indicator \(i\) reflects the factor), and \(\epsilon_i\) is measurement error. The model is fit by finding parameter values that best reproduce the observed covariance matrix among indicators.

Model fit indices

Every index in the report is listed with its reference in Fit indices in the report.

Modification indices

A modification index estimates how much \(\chi^2\) would drop if a currently-fixed parameter (typically a residual covariance, or a cross-loading) were freed and re-estimated. Large indices flag places where the model doesn’t match the data — but freeing parameters purely to improve fit, without substantive justification, risks overfitting to sample-specific noise rather than reflecting genuine structure.

Sample size and power for SEM

SEM fit indices and standard errors are sample-size dependent: small samples can fail to reject a poorly-fitting model (low power) while very large samples can flag trivial misfit as statistically significant. simulate_cfa_fit directly visualizes how fit indices stabilize as sample size grows, supporting sample-size planning before data collection.


Model Diagrams

plot_cfa_gg draws a path diagram directly in ggplot2 (no semPlot/Rgraphviz system dependency), with latent variables as filled rectangles, observed variables as light rectangles, and edges labeled with loadings.

model_syntax <- "LATENT1=~X1+X2+X3
                 LATENT2=~X4+X5+X6"
df_cfa <- lavaan::simulateData(model = model_syntax, model.type = "cfa", return.type = "data.frame", sample.nobs = 300)
fit <- lavaan::cfa(model_syntax, data = df_cfa)
plot_cfa_gg(fit, what = "std", layout = "tree")

plot_cfa_gg(fit, what = "est", layout = "circle")

what = "std" shows standardized loadings (comparable across indicators regardless of their original scale); what = "est" shows raw, unstandardized estimates (in the original metric of each indicator). Three layout options (tree, circle, spring) control node placement via igraph.

Equality constraints

what = "eq" labels each loading with its parameter label, so loadings constrained to be equal (sharing the same label) are easy to spot; loadings without a label show their estimate. It needs a model with labelled parameters. Here the loadings of X2 and X3 are constrained to be equal (a), and so are those of X5 and X6 (b):

model_eq <- "LATENT1=~X1+a*X2+a*X3
             LATENT2=~X4+b*X5+b*X6"
fit_eq <- lavaan::cfa(model_eq, data = df_cfa)
plot_cfa_gg(fit_eq, what = "eq", layout = "spring")

Styling

label_size and edge_label_size set the text size of the node and path labels; color_latent and color_observed set the fill colour of the latent and observed nodes:

plot_cfa_gg(fit, what = "std", layout = "tree",
            label_size = 4, edge_label_size = 3.5,
            color_latent = "#2c3e50", color_observed = "#ecf0f1")

All layouts at once

plot_cfa is a batch wrapper that runs every combination of layout × what in one call and returns them as a named list — useful for quickly picking the clearest arrangement for a report. The three eq diagrams are only produced for models with labelled parameters, so fit gives 6 diagrams and fit_eq gives all 9:

all_plots <- plot_cfa(fit)
all_plots_eq <- plot_cfa(fit_eq)
names(all_plots)
## [1] "circle_estimates"          "circle_standard_estimates" "tree_estimates"            "tree_standard_estimates"   "spring_estimates"          "spring_standard_estimates"
names(all_plots_eq)
## [1] "circle_estimates"                           "circle_standard_estimates"                  "circle_parameters_wih_equality_constraints" "tree_estimates"                             "tree_standard_estimates"                    "tree_parameters_wih_equality_constraints"   "spring_estimates"                           "spring_standard_estimates"                  "spring_parameters_wih_equality_constraints"

Any diagram can be taken from the list by name:

all_plots$spring_standard_estimates

Full CFA Report

report_cfa bundles fit indices, R², parameter estimates (unstandardized and standardized), modification indices, sample covariance, model-implied predicted scores, and the path diagrams into one structured report.

result <- report_cfa(model = fit)

result$fit_indices
##                                 fit
## npar                   1.300000e+01
## fmin                   9.795390e-03
## chisq                  5.877234e+00
## df                     8.000000e+00
## pvalue                 6.609813e-01
## baseline.chisq         4.499905e+02
## baseline.df            1.500000e+01
## baseline.pvalue        0.000000e+00
## cfi                    1.000000e+00
## tli                    1.009150e+00
## nnfi                   1.009150e+00
## rfi                    9.755110e-01
## nfi                    9.869392e-01
## pnfi                   5.263676e-01
## ifi                    1.004803e+00
## rni                    1.004880e+00
## logl                  -2.969640e+03
## unrestricted.logl     -2.966701e+03
## aic                    5.965279e+03
## bic                    6.013429e+03
## ntotal                 3.000000e+02
## bic2                   5.972200e+03
## rmsea                  0.000000e+00
## rmsea.ci.lower         0.000000e+00
## rmsea.ci.upper         5.458030e-02
## rmsea.ci.level         9.000000e-01
## rmsea.pvalue           9.305991e-01
## rmsea.close.h0         5.000000e-02
## rmsea.notclose.pvalue  4.125356e-03
## rmsea.notclose.h0      8.000000e-02
## rmr                    4.938356e-02
## rmr_nomean             4.938356e-02
## srmr                   2.429525e-02
## srmr_bentler           2.429525e-02
## srmr_bentler_nomean    2.429525e-02
## crmr                   2.874653e-02
## crmr_nomean            2.874653e-02
## srmr_mplus             2.429525e-02
## srmr_mplus_nomean      2.429525e-02
## gfi                    1.000000e+00
## gfi.ci.lower           9.921773e-01
## gfi.ci.upper           1.000000e+00
## gfi.ci.level           9.000000e-01
## cn_05                  7.925618e+02
## cn_01                  1.026494e+03
## gfi_lisrel             9.935428e-01
## agfi_lisrel            9.830498e-01
## pgfi                   3.784925e-01
## mfi                    1.003544e+00
## ecvi                   1.062574e-01
result$r_squared
##    r_squared
## X1 0.5067546
## X2 0.5413438
## X3 0.4589552
## X4 0.4565517
## X5 0.6738854
## X6 0.4511722
result$parameters
##        lhs op     rhs exo        est         se        z       pvalue    ci.lower  ci.upper     std.lv    std.all
## 1  LATENT1 =~      X1   0 1.00000000 0.00000000       NA           NA  1.00000000 1.0000000 1.02017714 0.71186696
## 2  LATENT1 =~      X2   0 1.06492177 0.12227716 8.709081 0.000000e+00  0.82526293 1.3045806 1.08640884 0.73576073
## 3  LATENT1 =~      X3   0 0.94115894 0.10824747 8.694512 0.000000e+00  0.72899779 1.1533201 0.96014883 0.67746232
## 4  LATENT2 =~      X4   0 1.00000000 0.00000000       NA           NA  1.00000000 1.0000000 0.91991042 0.67568608
## 5  LATENT2 =~      X5   0 1.33314945 0.14801629 9.006775 0.000000e+00  1.04304286 1.6232560 1.22637806 0.82090520
## 6  LATENT2 =~      X6   0 1.00262247 0.10935857 9.168212 0.000000e+00  0.78828362 1.2169613 0.92232285 0.67169352
## 7       X1 ~~      X1   0 1.01301661 0.13237075 7.652874 1.976197e-14  0.75357470 1.2724585 1.01301661 0.49324543
## 8       X2 ~~      X2   0 1.00000138 0.14281684 7.001985 2.523537e-12  0.72008552 1.2799172 1.00000138 0.45865615
## 9       X3 ~~      X3   0 1.08677603 0.12752028 8.522378 0.000000e+00  0.83684087 1.3367112 1.08677603 0.54104480
## 10      X4 ~~      X4   0 1.00730129 0.11390706 8.843186 0.000000e+00  0.78404756 1.2305550 1.00730129 0.54344833
## 11      X5 ~~      X5   0 0.72783516 0.15201154 4.788026 1.684302e-06  0.42989801 1.0257723 0.72783516 0.32611464
## 12      X6 ~~      X6   0 1.03480792 0.11582487 8.934246 0.000000e+00  0.80779534 1.2618205 1.03480792 0.54882782
## 13 LATENT1 ~~ LATENT1   0 1.04076139 0.17877176 5.821733 5.824062e-09  0.69037519 1.3911476 1.00000000 1.00000000
## 14 LATENT2 ~~ LATENT2   0 0.84623517 0.14949935 5.660461 1.509673e-08  0.55322183 1.1392485 1.00000000 1.00000000
## 15 LATENT1 ~~ LATENT2   0 0.07126109 0.07078279 1.006757 3.140514e-01 -0.06747063 0.2099928 0.07593314 0.07593314
## 16      X1 r2      X1   0 0.50675457         NA       NA           NA          NA        NA         NA         NA
## 17      X2 r2      X2   0 0.54134385         NA       NA           NA          NA        NA         NA         NA
## 18      X3 r2      X3   0 0.45895520         NA       NA           NA          NA        NA         NA         NA
## 19      X4 r2      X4   0 0.45655167         NA       NA           NA          NA        NA         NA         NA
## 20      X5 r2      X5   0 0.67388536         NA       NA           NA          NA        NA         NA         NA
## 21      X6 r2      X6   0 0.45117218         NA       NA           NA          NA        NA         NA         NA
result$modification_indices[order(-result$modification_indices$mi), ]
##        lhs op     rhs           mi           epc      sepc.all delta         ncp      power decision
## 33      X3 ~~      X6 2.726710e+00  1.253792e-01  1.182294e-01   0.1 1.734555534 0.26065653      (i)
## 23      X1 ~~      X3 2.472947e+00 -1.550222e+00 -1.477459e+00   0.1 0.010290277 0.05117960      (i)
## 20 LATENT2 =~      X2 2.472924e+00 -1.427474e-01 -8.893177e-02   0.1 1.213596945 0.19645587      (i)
## 30      X2 ~~      X6 1.065747e+00 -7.952232e-02 -7.817337e-02   0.1 1.685295436 0.25461851      (i)
## 25      X1 ~~      X5 7.257519e-01  6.591286e-02  7.676184e-02   0.1 1.670505270 0.25280369      (i)
## 19 LATENT2 =~      X1 7.091670e-01  7.396125e-02  4.747588e-02   0.1 1.296402951 0.20669092      (i)
## 27      X2 ~~      X3 7.091517e-01  9.108748e-01  8.737523e-01   0.1 0.008547159 0.05097966      (i)
## 22      X1 ~~      X2 6.732885e-01  9.943729e-01  9.879630e-01   0.1 0.006809303 0.05078038      (i)
## 21 LATENT2 =~      X3 6.732650e-01  7.151687e-02  4.641952e-02   0.1 1.316342813 0.20915513      (i)
## 26      X1 ~~      X6 5.947840e-01 -5.822505e-02 -5.686849e-02   0.1 1.754444255 0.26309143      (i)
## 28      X2 ~~      X4 4.287168e-01 -4.988266e-02 -4.970151e-02   0.1 1.722944721 0.25923426      (i)
## 35      X4 ~~      X6 3.989898e-01  4.897609e-01  4.797054e-01   0.1 0.016633875 0.05190762      (i)
## 17 LATENT1 =~      X5 3.989833e-01  5.299606e-02  3.618994e-02   0.1 1.420585978 0.22203085      (i)
## 24      X1 ~~      X4 2.700138e-01  3.879869e-02  3.840865e-02   0.1 1.793708048 0.26789305      (i)
## 16 LATENT1 =~      X4 1.923742e-01 -3.278983e-02 -2.457051e-02   0.1 1.789239312 0.26734693      (i)
## 36      X5 ~~      X6 1.923695e-01 -5.385531e-01 -6.205577e-01   0.1 0.006632527 0.05076011      (i)
## 32      X3 ~~      X5 1.625584e-01 -3.131018e-02 -3.520457e-02   0.1 1.658204966 0.25129374      (i)
## 34      X4 ~~      X5 9.867952e-02 -3.876797e-01 -4.527691e-01   0.1 0.006565700 0.05075245      (i)
## 18 LATENT1 =~      X6 9.867904e-02 -2.372751e-02 -1.762852e-02   0.1 1.752752963 0.26288444      (i)
## 31      X3 ~~      X4 7.694563e-02 -2.082969e-02 -1.990825e-02   0.1 1.773447327 0.26541624      (i)
## 29      X2 ~~      X5 7.310666e-03  6.762547e-03  7.926719e-03   0.1 1.598587304 0.24396746      (i)
## 15 LATENT1 ~~ LATENT2 6.286205e-12  1.753432e-07  1.868391e-07   0.1 2.044611177 0.29838308      (i)
## 6  LATENT2 =~      X6 2.140021e-12  1.125656e-07  7.541182e-08   0.1 1.688910195 0.25506193      (i)
## 10      X4 ~~      X4 1.967364e-12 -1.402558e-07 -5.434483e-01   0.1 1.000099314 0.17008729      (i)
## 5  LATENT2 =~      X5 1.333117e-12  8.439483e-08  5.196728e-08   0.1 1.871701659 0.27740859      (i)
## 14 LATENT2 ~~ LATENT2 1.234090e-12  9.700989e-08  1.000000e+00   0.1 1.311338154 0.20853667      (i)
## 3  LATENT1 =~      X3 9.918481e-13 -7.300700e-08 -5.255169e-08   0.1 1.860870770 0.27608905      (i)
## 13 LATENT1 ~~ LATENT1 5.391582e-13 -8.253152e-08 -1.000000e+00   0.1 0.791546572 0.14443613      (i)
## 11      X5 ~~      X5 2.483790e-13  5.256892e-08  3.261146e-01   0.1 0.898786988 0.15760680      (i)
## 7       X1 ~~      X1 2.305844e-13 -5.317121e-08 -4.932454e-01   0.1 0.815599435 0.14738587      (i)
## 12      X6 ~~      X6 1.254611e-13  3.621811e-08  5.488278e-01   0.1 0.956439431 0.16470518      (i)
## 8       X2 ~~      X2 4.188849e-14 -2.355895e-08 -4.586562e-01   0.1 0.754714689 0.13992469      (i)
## 2  LATENT1 =~      X2 3.103615e-14  1.280506e-08  8.847094e-09   0.1 1.892798485 0.27997702      (i)
## 9       X3 ~~      X3 2.509295e-15  5.618800e-09  5.410448e-01   0.1 0.794812364 0.14483647      (i)
  • fit_indices: the full lavaan fit table (CFI, TLI, RMSEA + CI, SRMR, AIC, BIC, etc.).
  • r_squared: proportion of each indicator’s variance explained by its latent factor.
  • parameters: every estimated parameter (loadings, variances, covariances) with SE, z, p, and confidence intervals.
  • modification_indices: sorted here by size — the largest values are the parameters most likely to improve fit if freed (again, only worth freeing with a substantive rationale).

The rest of the report holds the input data and model matrices:

result$sample_covariance
##          X1          X2         X3          X4         X5         X6
## 1 2.0537779  1.11061581 0.97366776  0.10761073 0.18349180  0.0538701
## 2 1.1106158  2.18028551 1.04593443 -0.03169393 0.04625917 -0.0433154
## 3 0.9736678  1.04593443 2.00866169  0.06915178 0.13837788  0.1694607
## 4 0.1076107 -0.03169393 0.06915178  1.85353633 1.12753597  0.8512851
## 5 0.1834918  0.04625917 0.13837788  1.12753597 2.23183857  1.1302200
## 6 0.0538701 -0.04331540 0.16946071  0.85128506 1.13021997  1.8854876
result$standardized_estimates
## $lambda
##      LATENT1   LATENT2
## X1 0.7118670 0.0000000
## X2 0.7357607 0.0000000
## X3 0.6774623 0.0000000
## X4 0.0000000 0.6756861
## X5 0.0000000 0.8209052
## X6 0.0000000 0.6716935
## attr(,"class")
## [1] "lavaan.matrix" "matrix"       
## 
## $theta
##           X1        X2        X3        X4        X5        X6
## X1 0.4932454 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000
## X2 0.0000000 0.4586562 0.0000000 0.0000000 0.0000000 0.0000000
## X3 0.0000000 0.0000000 0.5410448 0.0000000 0.0000000 0.0000000
## X4 0.0000000 0.0000000 0.0000000 0.5434483 0.0000000 0.0000000
## X5 0.0000000 0.0000000 0.0000000 0.0000000 0.3261146 0.0000000
## X6 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.5488278
## attr(,"class")
## [1] "lavaan.matrix.symmetric" "matrix"                 
## 
## $psi
##            LATENT1    LATENT2
## LATENT1 1.00000000 0.07593314
## LATENT2 0.07593314 1.00000000
## attr(,"class")
## [1] "lavaan.matrix.symmetric" "matrix"                 
## 
## attr(,"class")
## [1] "lavaan.list" "list"
head(result$predict)
##           X1         X2         X3        X4         X5         X6     LATENT1     LATENT2
## 1 -0.9426779 -2.1028008  0.1912442  3.276463  2.9851827  2.7977557 -0.67595179  1.98070180
## 2  0.8063454  0.4591551 -2.2035808  1.981226  3.7663648  0.9178366 -0.07195081  1.68983705
## 3  2.1002916  0.7484383  0.5253228  2.128261 -0.5622396 -0.3917101  0.90638917  0.08619589
## 4  0.3554615  0.4818293 -0.1334990  1.355596  0.3903519 -2.0340665  0.24361619 -0.03310564
## 5 -1.8511984 -0.9792688 -1.7832304 -2.503643  0.4967461  0.1956658 -1.08521488 -0.31626076
## 6  0.4841860 -0.3228088 -0.6920372  1.614947  5.5834426  1.4969346 -0.01824073  2.32081883
result$call
##                                                                call
## 1   lavaan::lavaan(model=model_syntax,data=df_cfa,model.type="cfa",
## 2 cmd="cfa",int.ov.free=TRUE,int.lv.free=FALSE,auto.fix.first=TRUE,
## 3            auto.fix.single=TRUE,auto.var=TRUE,auto.cov.lv.x=TRUE,
## 4       auto.cov.y=TRUE,auto.th=TRUE,auto.delta=TRUE,auto.efa=TRUE)
  • sample_covariance: the observed covariance matrix of the indicators that the model tries to reproduce.
  • unstandardized_estimates / standardized_estimates: the model matrices — lambda (loadings), theta (residual variances and covariances) and psi (factor variances and covariances).
  • predict: the observed data with each case’s predicted factor scores added as extra columns.
  • call: the lavaan call that fitted the model.

With file, the report is also saved: report_cfa(fit, file = "cfa") writes every table to cfa.xlsx and all diagrams to cfa_diagram.pdf, with w and h setting the PDF page size in inches.

Fit indices in the report

result$fit_indices holds every fit measure lavaan computes (Rosseel, 2012). Cut-offs are given only where the literature gives one; “lower is better” indices are for comparing models fitted to the same data. The _nomean variants ignore the mean structure, so they equal the plain index when the model has no means, as here.

Row in fit_indices Index Good fit Reference
npar Number of free parameters — —
fmin Minimum of the fit function, \(\chi^2/(2N)\) — Jöreskog (1969)
chisq, df, pvalue \(\chi^2\) test of exact fit \(p > .05\) Jöreskog (1969)
baseline.chisq, baseline.df, baseline.pvalue \(\chi^2\) test of the baseline (independence) model, used by the incremental indices — Bentler & Bonett (1980)
cfi Comparative Fit Index \(\geq .95\) Bentler (1990); Hu & Bentler (1999)
tli, nnfi Tucker-Lewis Index / Non-Normed Fit Index (same value) \(\geq .95\) Tucker & Lewis (1973); Bentler & Bonett (1980); Hu & Bentler (1999)
rfi Relative Fit Index close to 1 Bollen (1986)
nfi Normed Fit Index \(\geq .90\) Bentler & Bonett (1980)
pnfi Parsimony Normed Fit Index higher is better James et al. (1982)
ifi Incremental Fit Index close to 1 Bollen (1989a)
rni Relative Noncentrality Index \(\geq .95\) McDonald & Marsh (1990); Hu & Bentler (1999)
logl, unrestricted.logl Log-likelihood of the model and of the saturated model — Jöreskog (1969)
aic Akaike Information Criterion lower is better Akaike (1974)
bic Bayesian Information Criterion lower is better Schwarz (1978)
ntotal Total sample size — —
bic2 Sample-size adjusted BIC lower is better Sclove (1987)
rmsea Root Mean Square Error of Approximation \(\leq .06\) Steiger & Lind (1980); Steiger (1990); Hu & Bentler (1999)
rmsea.ci.lower, rmsea.ci.upper, rmsea.ci.level 90% confidence interval of RMSEA — Browne & Cudeck (1992)
rmsea.pvalue, rmsea.close.h0 Test of close fit, \(H_0\): RMSEA \(\leq .05\) \(p > .05\) Browne & Cudeck (1992)
rmsea.notclose.pvalue, rmsea.notclose.h0 Test of not-close fit, \(H_0\): RMSEA \(\geq .08\) \(p < .05\) MacCallum et al. (1996)
rmr, rmr_nomean Root Mean Square Residual (unstandardized, depends on the scale of the variables) — Jöreskog & Sörbom (1981)
srmr, srmr_bentler, srmr_bentler_nomean Standardized Root Mean Square Residual \(\leq .08\) Bentler (1995); Hu & Bentler (1999)
crmr, crmr_nomean Correlation Root Mean Square Residual (residual correlations, diagonal excluded) — Bollen (1989b)
srmr_mplus, srmr_mplus_nomean SRMR as computed by Mplus \(\leq .08\) Asparouhov & Muthén (2018)
gfi, gfi.ci.lower, gfi.ci.upper, gfi.ci.level Goodness of Fit Index, with confidence interval close to 1 Jöreskog & Sörbom (1981)
cn_05, cn_01 Hoelter’s critical N at \(\alpha = .05\) and \(.01\) \(> 200\) Hoelter (1983)
gfi_lisrel, agfi_lisrel GFI and Adjusted GFI as computed by LISREL close to 1 Jöreskog & Sörbom (1981)
pgfi Parsimony Goodness of Fit Index higher is better Mulaik et al. (1989)
mfi McDonald’s Fit Index close to 1 McDonald (1989)
ecvi Expected Cross-Validation Index lower is better Browne & Cudeck (1989)

Multi-group models

When the fitted model has more than one group, report_cfa additionally returns a group summary table (group labels, sample sizes per group, and total N) — omitted here since the example above is single-group.

Sample Size Planning

simulate_cfa_fit refits a CFA model repeatedly across a range of sample sizes, in parallel, and returns fit indices at each size — either generating data from known population parameters (model_sim) or resampling from an observed dataset’s correlation structure (df).

model_sim <- "LATENT =~ 1*X1 + 0.5*X2 + 1.5*X3 + 1.5*X4 + X5"
model_est <- "LATENT =~ X1 + X2 + X3 + X4 + X5"
result_sim <- simulate_cfa_fit(model_sim = model_sim, model = model_est, minnobs = 50, maxnobs = 10000, stepping = 100)

The first element is a table with one row per sample size and one column per fit index; the second is a named list of plots, one per fit index:

head(result_sim[[1]][, c("observations", "cfi", "tli", "rmsea", "srmr")])
##   observations       cfi       tli      rmsea        srmr
## 1           50 0.9831898 0.9663796 0.08100305 0.051864543
## 2          150 1.0000000 1.0198220 0.00000000 0.017967412
## 3          250 1.0000000 1.0083660 0.00000000 0.017219490
## 4          350 1.0000000 1.0092316 0.00000000 0.009174356
## 5          450 1.0000000 1.0008744 0.00000000 0.014185840
## 6          550 1.0000000 1.0009186 0.00000000 0.011635798
plot_multiplot(plotlist = result_sim[[2]][c("observations_cfi", "observations_tli",
                                            "observations_rmsea", "observations_srmr")],
               cols = 2)
## [[1]]

Each panel tracks one fit index against sample size. Indices like RMSEA and SRMR typically stabilize and tighten (less sample-to-sample variability) as \(n\) grows — the point at which a given index’s variability becomes acceptably small for your purposes is a data-driven answer to “how large a sample do I need?” for this specific model.


Conclusion

plot_cfa_gg/plot_cfa visualize a fitted measurement model’s structure without requiring semPlot’s system dependencies; report_cfa collects every quantity needed to write up a CFA (fit, parameters, R², modification indices) in one call; and simulate_cfa_fit turns “what sample size do I need” into an empirical, visualizable question rather than a rule of thumb.

References

Akaike, H. (1974). A new look at the statistical model identification. IEEE Transactions on Automatic Control, 19(6), 716–723. https://doi.org/10.1109/TAC.1974.1100705

Asparouhov, T., & Muthén, B. (2018). SRMR in Mplus [Technical report]. Muthén & Muthén. https://www.statmodel.com/download/SRMR2.pdf

Bentler, P. M. (1990). Comparative fit indexes in structural models. Psychological Bulletin, 107(2), 238–246. https://doi.org/10.1037/0033-2909.107.2.238

Bentler, P. M. (1995). EQS structural equations program manual. Multivariate Software.

Bentler, P. M., & Bonett, D. G. (1980). Significance tests and goodness of fit in the analysis of covariance structures. Psychological Bulletin, 88(3), 588–606. https://doi.org/10.1037/0033-2909.88.3.588

Bollen, K. A. (1986). Sample size and Bentler and Bonett’s nonnormed fit index. Psychometrika, 51(3), 375–377. https://doi.org/10.1007/BF02294061

Bollen, K. A. (1989a). A new incremental fit index for general structural equation models. Sociological Methods & Research, 17(3), 303–316. https://doi.org/10.1177/0049124189017003004

Bollen, K. A. (1989b). Structural equations with latent variables. Wiley. https://doi.org/10.1002/9781118619179

Browne, M. W., & Cudeck, R. (1989). Single sample cross-validation indices for covariance structures. Multivariate Behavioral Research, 24(4), 445–455. https://doi.org/10.1207/s15327906mbr2404_4

Browne, M. W., & Cudeck, R. (1992). Alternative ways of assessing model fit. Sociological Methods & Research, 21(2), 230–258. https://doi.org/10.1177/0049124192021002005

Hoelter, J. W. (1983). The analysis of covariance structures: Goodness-of-fit indices. Sociological Methods & Research, 11(3), 325–344. https://doi.org/10.1177/0049124183011003003

Hu, L., & Bentler, P. M. (1999). Cutoff criteria for fit indexes in covariance structure analysis: Conventional criteria versus new alternatives. Structural Equation Modeling, 6(1), 1–55. https://doi.org/10.1080/10705519909540118

James, L. R., Mulaik, S. A., & Brett, J. M. (1982). Causal analysis: Assumptions, models, and data. Sage.

Jöreskog, K. G. (1969). A general approach to confirmatory maximum likelihood factor analysis. Psychometrika, 34(2), 183–202. https://doi.org/10.1007/BF02289343

Jöreskog, K. G., & Sörbom, D. (1981). LISREL V: Analysis of linear structural relationships by maximum likelihood and least squares methods. National Educational Resources.

MacCallum, R. C., Browne, M. W., & Sugawara, H. M. (1996). Power analysis and determination of sample size for covariance structure modeling. Psychological Methods, 1(2), 130–149. https://doi.org/10.1037/1082-989X.1.2.130

McDonald, R. P. (1989). An index of goodness-of-fit based on noncentrality. Journal of Classification, 6(1), 97–103. https://doi.org/10.1007/BF01908590

McDonald, R. P., & Marsh, H. W. (1990). Choosing a multivariate model: Noncentrality and goodness of fit. Psychological Bulletin, 107(2), 247–255. https://doi.org/10.1037/0033-2909.107.2.247

Mulaik, S. A., James, L. R., Van Alstine, J., Bennett, N., Lind, S., & Stilwell, C. D. (1989). Evaluation of goodness-of-fit indices for structural equation models. Psychological Bulletin, 105(3), 430–445. https://doi.org/10.1037/0033-2909.105.3.430

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

Schwarz, G. (1978). Estimating the dimension of a model. The Annals of Statistics, 6(2), 461–464. https://doi.org/10.1214/aos/1176344136

Sclove, S. L. (1987). Application of model-selection criteria to some problems in multivariate analysis. Psychometrika, 52(3), 333–343. https://doi.org/10.1007/BF02294360

Steiger, J. H. (1990). Structural model evaluation and modification: An interval estimation approach. Multivariate Behavioral Research, 25(2), 173–180. https://doi.org/10.1207/s15327906mbr2502_4

Steiger, J. H., & Lind, J. C. (1980). Statistically based tests for the number of common factors [Paper presentation]. Annual meeting of the Psychometric Society, Iowa City, IA, United States.

Tucker, L. R., & Lewis, C. (1973). A reliability coefficient for maximum likelihood factor analysis. Psychometrika, 38(1), 1–10. https://doi.org/10.1007/BF02291170


Rendered with R 4.6.1 · lavaan 0.7.2