Contents
- Overview
- Latent Variables and Composites
- Model Matrices and the
_cSuffix - Example: Composites Predicting an Observed Variable
- The Composite Network Model: cnm()
- Combining a Latent Variable and a Composite
- A Network of Constructs
- Scaling and Identification
- Estimation
- Relation to lavaan
- Experimental Status and Limitations
- Summary
Overview Experimental (0.18)
The cvm family models structural equation models that contain both latent variables (common factors) and composites. It implements the factor- and composite-based SEM framework of Schamberger, Schuberth, Henseler and Rosseel (2025), and extends it in the way psychonetrics extends other model families: every variance–covariance structure in the model can also be modeled as a network.
cvm(): the general model, with factor loadings (lambda), composite weights (weights), regressions between the constructs (beta) and three covariance structures that can each be parameterized in several ways.cnm(): the composite network model, a wrapper that models the indicators within every composite as a partial correlation network.
Latent Variables and Composites
A latent variable is a common cause of its indicators and is measured with error. A composite is the opposite: an exact weighted sum of its indicators, without any error. Both are called constructs below. Every observed variable is either an indicator of latent variables ($\boldsymbol{y}_f$) or an indicator of exactly one composite ($\boldsymbol{y}_c$):
$$\boldsymbol{y}_f = \boldsymbol{\nu}_f + \boldsymbol{\Lambda}\,\boldsymbol{\eta}_f + \boldsymbol{\varepsilon}, \qquad \boldsymbol{\eta}_c = \boldsymbol{W}^{\top} \boldsymbol{y}_c, \qquad \boldsymbol{\eta} = \boldsymbol{\nu}_\eta + \boldsymbol{B}\,\boldsymbol{\eta} + \boldsymbol{\zeta}$$
- $\boldsymbol{\Lambda}$ (
lambda): the factor loadings of the latent variables. - $\boldsymbol{W}$ (
weights): the weights with which indicators form their composite. - $\boldsymbol{B}$ (
beta): the regressions between constructs, which can be latent variables or composites in any combination.
The composite model does not explain why the indicators of a composite are correlated: these variances and covariances are free parameters. What it does impose is that the indicators of a composite relate to everything else in the model only through the composite. That restriction is what makes the model testable.
lambda) gives the same model. A variable cannot load directly on a composite: effects between constructs are always specified in beta.
Model Matrices and the _c Suffix
The family has three covariance structures, each with its own type argument:
| Argument | What it models | Suffix | Types |
|---|---|---|---|
latent |
(Residual) variances and covariances of the constructs | _zeta |
"cov", "ggm" |
residual |
Residuals of the indicators of latent variables | _epsilon |
"cov", "chol", "prec", "ggm", "cor" |
composite |
Variances and covariances of the indicators of composites | _c |
"cov", "chol", "prec", "ggm", "cor" |
The matrices with the suffix _c (sigma_c, omega_c, delta_c, kappa_c, lowertri_c, rho_c, SD_c) describe the indicators of composites. They are block diagonal with one block per composite: elements within a block are parameters, whereas elements that connect indicators of different composites are always zero, because those covariances are implied by the relations between the composites.
_c does not refer to relations between composites. Those are modeled, like relations between latent variables, in beta and the _zeta matrices.
Some quantities are computed rather than estimated. The variance of a composite follows from its weights and the covariances of its indicators, so the (residual) variances and the intercepts of composites are not parameters. They are shown in the parameter table without standard errors. getmatrix() also returns a few derived matrices: the composite loadings (in the columns of lambda that belong to composites), the implied covariances and means of the constructs (sigma_eta, mu_eta), and the implied residual covariances of the composite indicators (sigma_epsilon_c).
Example: Composites Predicting an Observed Variable
The StarWars data (271 respondents) contain three questions on the original trilogy (Q5–Q7), three on the sequel trilogy (Q8–Q10), and the item “I am a huge Star Wars fan!” (Q1). We form one composite per trilogy and use both to predict being a fan:
library("psychonetrics")
library("dplyr")
data(StarWars)
vars <- c("Q1", paste0("Q", 5:10))
# Weights: which variables form which composite. Q1 is a composite with a
# single indicator, which represents the observed variable itself:
weights <- matrix(0, 7, 3)
weights[1, 1] <- 1 # Fan
weights[2:4, 2] <- 1 # Originals
weights[5:7, 3] <- 1 # Sequels
# Both composites predict being a fan (they are correlated by default):
beta <- matrix(0, 3, 3)
beta[1, 2:3] <- 1
mod <- cvm(StarWars, weights = weights, beta = beta, vars = vars,
latents = c("Fan", "Originals", "Sequels")) %>% runmodel
mod %>% fit # chi-square = 2.92, df = 8, p = 0.94
mod %>% parameters
getmatrix(mod, "weights") # estimated weights
getmatrix(mod, "lambda") # composite loadings
The model fits well. The weights and effects are:
| Parameter | Estimate | SE |
|---|---|---|
| Q5 → Originals | 1 (fixed) | |
| Q6 → Originals | 2.72 | 0.89 |
| Q7 → Originals | 0.81 | 0.39 |
| Q8 → Sequels | 1 (fixed) | |
| Q9 → Sequels | −0.23 | 0.22 |
| Q10 → Sequels | 1.22 | 0.37 |
| Originals → Fan | 0.17 | 0.050 |
| Sequels → Fan | 0.13 | 0.040 |
The first weight of every composite is fixed to 1 to set its scale, so the other weights are relative to that indicator. Weights are estimated from the relations of a composite with the rest of the model, and therefore tend to have larger standard errors than factor loadings.
The Composite Network Model: cnm()
With composite = "ggm", or the wrapper cnm(), the indicators within each composite are modeled as a Gaussian graphical model: omega_c contains one partial correlation network per composite. With all edges included this is the same model as above in another parameterization. The networks can then be made sparse with the usual tools:
mod_cnm <- cnm(StarWars, weights = weights, beta = beta, vars = vars,
latents = c("Fan", "Originals", "Sequels")) %>% runmodel
# Remove non-significant edges within the composites:
mod_cnm_pruned <- mod_cnm %>% prune(alpha = 0.05)
compare(full = mod_cnm, pruned = mod_cnm_pruned)
# model DF AIC BIC RMSEA Chisq Chisq_diff DF_diff p_value
# full 8 5799.02 5896.27 ~ 0 2.92
# pruned 10 5800.94 5890.99 ~ 0 8.84 5.92 2 0.052
# One network per composite:
getmatrix(mod_cnm_pruned, "omega_c")
Pruning removes the two edges that involve Q9, leaving a fully connected network of the three questions on the original trilogy (partial correlations 0.26, 0.16 and 0.38) and a single edge between Q8 and Q10 (0.37) for the sequels. prune(), stepup() and modelsearch() never add edges between indicators of different composites.
Because the unpruned cnm model is the cvm model in another parameterization, a fitted model can also be transformed from one to the other with transmod(), without estimating it again:
# cvm -> cnm (covariances of the composite indicators -> networks):
mod_cnm2 <- transmod(mod, composite = "ggm", keep_computed = TRUE)
# cnm -> cvm:
mod_cvm2 <- transmod(mod_cnm, composite = "cov", keep_computed = TRUE)
This works when every composite is saturated (all covariances or all edges among its indicators), and also for the other types ("chol", "prec", "cor"), the residual type and the latent type ("cov" or "ggm").
Combining a Latent Variable and a Composite
Latent variables and composites can be combined freely. Here the sequel questions are modeled as indicators of a latent variable, predicted by a composite of the questions on the original trilogy:
vars2 <- paste0("Q", 5:10)
lambda2 <- matrix(0, 6, 2)
lambda2[4:6, 2] <- 1 # Sequels: a latent variable
weights2 <- matrix(0, 6, 2)
weights2[1:3, 1] <- 1 # Originals: a composite
beta2 <- matrix(0, 2, 2)
beta2[2, 1] <- 1 # Originals -> Sequels
mod2 <- cvm(StarWars, lambda = lambda2, weights = weights2, beta = beta2,
vars = vars2, latents = c("Originals", "Sequels")) %>% runmodel
mod2 %>% fit # chi-square = 3.01, df = 6, p = 0.81
mod2 %>% parameters # Sequels <- Originals: 0.17 (SE 0.059)
A construct is a latent variable when it has elements in lambda and a composite when it has elements in weights; it cannot have both, and a variable cannot be an indicator of a composite and load on a latent variable at the same time.
A Network of Constructs
With latent = "ggm" the relations between the constructs are modeled as a partial correlation network (omega_zeta) instead of covariances, as in the latent network model of the lvm family:
mod3 <- cvm(StarWars, weights = weights, vars = vars, latent = "ggm",
latents = c("Fan", "Originals", "Sequels")) %>% runmodel
getmatrix(mod3, "omega_zeta")
The estimated partial correlations are 0.525 between being a fan and the composite of the original trilogy, 0.228 between being a fan and the composite of the sequels, and 0.259 between the two composites. With all three edges included, this model is equivalent to the first example (chi-square = 2.92, df = 8).
latent = "ggm", a composite can either be a node in the latent network or have incoming effects in beta, but not both. Such models are refused with an informative error, and the model search functions do not propose them. Which of the two a composite is follows from the model as you specify it; after adding or removing effects on composites by hand, identify() updates which parameters model search may add.
Scaling and Identification
- Scaling. A composite is scaled by fixing the weight of one indicator to 1, by default the first. If the first indicator is a poor choice (its starting weight is near zero relative to the others, so that the other weights would become extremely large), another indicator is used and a message is shown; lavaan does the same. Set
bad_marker_crit = 0to always use the first indicator. - Choosing the scaling yourself. Free the fixed weight with
freepar()and fix another withfixpar(). The same functions can fix all weights of a composite, for example to form a sum score. The scaling does not change the fit of the model, but it does change the weights and the effects of and on the composite. - Isolated composites. A composite with estimated weights must be related to at least one other construct. The weights of a composite that is not related to anything are not identified, and a warning is given.
- Latent variables are identified as in the lvm family (
identification = "loadings"or"variance").
Estimation
The estimators "ML", "FIML" (chosen automatically with missing data), "ULS", "WLS" and "DWLS" are available, for single and multiple groups with equality constraints (equal, groupequal()) and with a mean structure. The model is implemented in both the R and the C++ pipeline, which give identical results.
Composite weights are only weakly identified, which makes the likelihood flat in some directions. Estimation starts from partial least squares estimates of the weights and uses the same optimizer and settings as all other model families. The optimizer can therefore stop slightly before the optimum: the chi-square is typically accurate to about two decimals. Stricter convergence criteria can be set with setoptimizer(), for example setoptimizer(mod, "nlminb", optim.args = list(control = list(rel.tol = 1e-10, eval.max = 20000, iter.max = 10000))). A warning is given when the optimizer does not report convergence, when the indicator that scales a composite has a negligible weight, when a composite with estimated weights is not related to any other construct, or when the computed residual variance of a composite is not positive.
estimator = "PML" penalizes the network structures in the model, after which refit() gives unpenalized estimates of the selected network. This works, but the optimizer used for penalized estimation is a first-order method and can be very slow for composite models (minutes for a model with a dozen variables). For now, prune() and stepup() are the faster route to a sparse network.
Relation to lavaan
Models with covariance parameterizations (latent, residual and composite all "cov") are the models that lavaan 0.7 and later estimate with the <~ operator, and can be converted in both directions with fromlavaan() and tolavaan():
library("lavaan")
# psychonetrics -> lavaan:
lavfit <- tolavaan(mod2)
fitMeasures(lavfit, c("chisq", "df", "npar")) # 3.01, 6, 21: as above
# lavaan -> psychonetrics:
fit <- sem(' Originals <~ Q5 + Q6 + Q7
Sequels =~ Q8 + Q9 + Q10
Sequels ~ Originals ',
data = StarWars, meanstructure = TRUE, composites.cov = "free")
mod_from_lavaan <- fromlavaan(fit, run = TRUE)
One difference in defaults is worth knowing. lavaan by default fixes the variances and covariances of composite indicators to their sample values, whereas psychonetrics estimates them (composites.cov = "free" in lavaan). With complete data both give the same chi-square, degrees of freedom, weights, loadings and regressions with the same standard errors, but the number of parameters differs, and with it AIC and BIC. For the model above, the lavaan defaults count 9 parameters where psychonetrics counts 21: the difference is the six means of the observed variables and the six variances and covariances of Q5–Q7. Network parameterizations ("ggm", "prec") have no lavaan counterpart.
Experimental Status and Limitations
The family is new in version 0.18 and is marked experimental. What has been checked:
- The analytic gradient and Fisher information against an independent implementation of the model and numerical differentiation.
- The R pipeline against the C++ pipeline, and both against lavaan wherever lavaan can estimate the same model, including multi-group and missing-data models.
- Simulations of bias, standard errors, coverage, the chi-square distribution and the recovery of networks within composites and between constructs.
Current limitations:
- Ordinal data and correlation input are not supported.
latentcan only be"cov"or"ggm".- With
latent = "ggm", a composite cannot have both incoming effects and edges in the latent network. - In small samples (around 250 or fewer) with weak relations between constructs, the weights can be poorly determined: standard errors are then very large, and the optimizer can stop on a flat part of the likelihood. Check the warnings and the standard errors, estimate the model again with stricter convergence criteria, and consider another indicator to scale the composite.
- The optimizer can stop slightly before the optimum in the weights: the chi-square is accurate to about two decimals (within 0.005 of lavaan in the models that were compared).
setoptimizer()gives stricter convergence (see Estimation). - Large models are slow: about 10 to 20 seconds for 36 variables, and minutes for 64 variables.
- Penalized estimation can be slow (see above).
Summary
cvm()estimates structural equation models with latent variables (lambda) and composites (weights) in any combinationcnm()models the indicators within every composite as a partial correlation network (omega_c), which can be made sparse withprune()andstepup()- The
_cmatrices describe the indicators of composites, not the relations between composites - Variances and intercepts of composites are computed, not estimated
- Models can be converted to and from lavaan with
tolavaan()andfromlavaan() - The family is experimental in version 0.18
Further Reading
- Schamberger, T., Schuberth, F., Henseler, J., & Rosseel, Y. (2025). Factor- and composite-based structural equation modeling: A new approach to incorporate composites in the traditional SEM framework. arXiv preprint arXiv:2508.06112. DOI: 10.48550/arXiv.2508.06112
- Schuberth, F., Henseler, J., & Dijkstra, T. K. (2018). Confirmatory composite analysis. Frontiers in Psychology, 9, 2541. DOI: 10.3389/fpsyg.2018.02541
- Henseler, J. (2021). Composite-based structural equation modeling: Analyzing latent and emergent variables. Guilford Press.
- Dijkstra, T. K. (2017). A perfect match between a model and a mode. In H. Latan & R. Noonan (Eds.), Partial least squares path modeling (pp. 55–80). Springer.
- Bollen, K. A., & Bauldry, S. (2011). Three Cs in measurement models: Causal indicators, composite indicators, and covariates. Psychological Methods, 16(3), 265–284.
- Epskamp, S., Rhemtulla, M., & Borsboom, D. (2017). Generalized network psychometrics: Combining network and latent variable models. Psychometrika, 82(4), 904–927.