0.6 series
Version 0.6-13
- Released on CRAN: 9 Jan 2023
- New features and user-visible changes:
- a new function efa() allows for classic (single-group) explorary
factor analysis
- a new function lavPredictY() allows for the prediction of ‘y’ values
based on ‘x’ values (see ?lavPredictY for a reference)
- a new function lavTest() allows to extract (or compute) one or several
test statistics based on an already fitted object
- new test statistics: browne.residual.adf and browne.residual.nt
- summary() and fitMeasures() gain an fm.args= argument, allowing to set
options (e.g., rmsea.ci.level) related to fit measures
- lavTestLRT() will now provide the RMSEA based on the difference test
- robust CFI and RMSEA are now computed for more settings: when (all)
data is categorical/ordered, when data is continuous but the estimator
is MLMV, and when missing = “ml”
(based on work done by Victoria Savalei and colleagues)
- new global option scaled.test= determines which test statistic will be
scaled (if multiple test statistics have been requested)
- new option gamma.unbiased: if set TRUE, an unbiased version of the so-called
Gamma matrix will be used, instead of the regular (biased) version. See
this paper
- iseed now works correctly in bootstrapLavaan() and related functions
thanks to a patch provided by Shu Fai Cheung
- bootstrapLavaan() now always returns all bootstrap runs (not just the
converged ones); it also warns about non-admissible solutions
- when bounds = “standard” or “wide”, bounds are now also computed for
covariances per default
- the output of lavInspect() for “gamma”, “wls.v”, “wls.obs” and “wls.est”
now includes labels
- the sam() function gains alpha.correction= argument to allow for small
sample corrections
- Important bug fix:
- in all lavaan versions < 0.6-13, there was on error in the computation
of scaled (difference) test statistics if 1) a mean and variance
adjusted test was used (i.e., test = “scaled.shifted”, or
test = “mean.var.adjusted”), 2) multiple groups were involved, and
3) equality constraints (across groups) were involved. A typical setting
are measurement invariance tests when data is categorical.
In those settings, the resulting test statistic was slightly off
(typically <5%).
Many thanks
to Steffen Gronneberg, Njal Foldnes and Jonas Moss for reporting this.
- Bugs/glitches discovered after the release:
Version 0.6-12
- Released on CRAN: 4 July 2022
- New features and user-visible changes:
- twolevel SEM now also supports conditional.x = TRUE
- out <- summary(fit) is now completely silent (i.e., nothing is printed);
out contains a list with ingredients (github issue 193)
- parameterEstimates() gains boot.ci.type = “bca” (for the single-group
setting only, for now)
- syntax: allow for partial specifications of thresholds (github issue 215)
- lavaanify() gains a nthresholds= argument (see github issue 214)
- when bootstrapping is used, a warning is printed informing the user
how many solutions were not admissible (see github issue 235)
- Bugs/glitches discovered after the release:
- standardizedSolution() did not work if representation = “RAM”
- iseed did not work properly in bootstrapLavaan() and other
bootstrap routines
- the sam() function did not work (any longer) with categorical data
- the scaled (difference) mean-and-variance adjusted test statistic is
wrong in the case of multiple groups involving equality constraints
Version 0.6-11
- Released on CRAN: 31 March 2022
- New features and user-visible changes:
- this is (again) only a maintenance release to prepare for R 4.2
- new option ceq.simple; when set to TRUE, a more compact representation
is used in the parameter table if only simple equality constraints are
used; the default is FALSE (for now)
- Bugs/glitches discovered after the release:
- ridge= option did not work properly
- df counting bug when nlevels > 1L, ngroups > 1L and fixed.x = TRUE
- EPC decisions were not based on the absolute value (pull request 231)
- name clash between ‘cl’ argument and ‘cluster’ argument
- interaction terms defined by a colon (a:b) were included in
lavNames(,”ov.x”) even if either a or b is a dependent variable
- standardizedSolution() did not work if representation = “RAM”
Version 0.6-10
- Released on CRAN: 25 January 2022
- New features and user-visible changes:
- this is a maintenance release, with mostly minor changes under
the hood (the github issues >214 were not yet addressed in this release)
- initial support for representation = “RAM”
- better starting values for regression coefficients, when all variables
are observed
- sam(): an indicator can now also be a predictor in the structural part
- estimator DLS: allow for non-positive Gamma, and allow sample.cov.rescale
to be set by the user
- new rotation criteria: bi-quartimin and bi-geomin
- Bugs/glitches discovered after the release:
- if all data is missing for a pair of variables, the degrees of freedom
should be adapted
Version 0.6-9
- Released on CRAN: 27 June 2021
- New features and user-visible changes:
- the sam() function is now public
- initial support for multilevel + missing = “ml”; only for
estimator = “ML” (not “MLR”)
- if missing = “two-stage”, h1.information is now always set to “unstructured”
- group.w.free = TRUE now also works for DWLS/WLS/WLSMV estimators
- Bugs/glitches discovered after the release:
- multilevel+missing=”ml” did not work if there was only 1 variabele on the
within level
- see github issues >214
Version 0.6-8
- Released on CRAN: 10 March 2021
- New features and user-visible changes:
- new estimator = “DLS” for distributionally-weighted
least squares (see Du, H., & Bentler, P.M. (in press).
Distributionally-weighted least squares in structural equation modeling.
Psychological Methods.)
- new optimizer: optim = “GN” provides Gauss-Newton optimization
- group.w.free = TRUE now also works in the categorical case
- the information=, observed.information= and h1.information= arguments now
accept a vector of two elements, eg information = c(“observed”, “expected”);
the first entry is used for the standard errors, while the second entry
is used for the test statistic
- new arguments omega.information=, omega.h1.information=,
omega.information.mean=, and omega.h1.information.meat= allow for even
more variants of various robust test statistics
- test = “yuan.bentler” now always uses observed.information = “h1”
(if information is observed) and omega.h1.information = “unstructured”
- lavResiduals() has a new output = “table” argument
- rotations.se = “bordered” per default (only used when rotation is used)
- in a multiple group analysis, a single modifier is always recycled
accross; this is now also true for labels (with a warning, unless
group.equal= is used)
- Known issues:
- Bugs/glitches discovered after the release:
- standardizedSolution() did not show labels (if any)
- lavResiduals() gave wrong results when the solution was rotated
- lav_mvnorm_missing_h1.R sometimes failed to produce starting
values (and stopped with an error)
- a check to force the (co)variance matrix of standardized parameters to
be positive definite was too strict (and is now omitted)
- lavTestLRT + satorra2002 + A.method = “exact” did not work when equality
constraints were involved (github issue 211)
Version 0.6-7
- Released on CRAN: 31 July 2020
- New features and user-visible changes:
- latent ~~ observed formulas are now supported; the observed variables
are automatically upgraded to (single-indicator) latent variables
- new option check.lv.names: when set to FALSE, lavaan proceeds even if
it detects that some latent variable names occur in the dataset
- optimization is made somewhat more robust: if a first attempt fails
(no convergence) three additional attempts are made (with
optim.parscale= “standardize”, with start = “simple”, and with the
combination optim.parscale = “standardized” and start = “simple”)
- the second argument of lavPredict() is now newdata (instead of type),
to be consistend with predict()
- Known issues:
- Bugs/glitches discovered after the release:
- fitMeasures() did not longer work for estimator = “PML”
- lavPredict + newdata + categorical did not work
- lavCor() did not listen to the missing = “fiml” argument
- lavPredict + Bartlett + missing: if all indicators
of a factor are missing, the factor score was 0 (should be NA)
- block syntax for groups was no longer working
Version 0.6-6
- Released on CRAN: 13 May 2020
- New features and user-visible changes:
- lavPredict() + se = TRUE now works correctly in the presence of
missing data and missing = “fiml”
- lavResiduals() + summary = TRUE now provides confidence intervals and
better labelling
- lavResiduals() + summary = TRUE now works for categorical data, but
only in models without exogenous covariates (for now)
- lavCor() gains cor.smooth= argument to force the correlation matrix
to be positive definite
- sum(sampling.weights) no longer needs to equal the total sample size
- sampling.weights can now be used in combination with categorical data
and estimator WLSMV and friends
- information/h1.information/observed.information arguments now accept
a vector of two elements: the first one is for the standard errors, the
second for the test statistic
- the data (provided by the data= argument) is now always converted to
a data.frame (in case it is a tibble, or another class that inherits
from data.frame)
- experimental feature: when the sample size is (very) small, adding the
argument bounds = TRUE may stabilize estimation, by automatically
choosing upper and lower bounds for several sets of model parameters
- Known issues:
- Bugs/glitches discovered after the release:
- lavPredict + method=”Bartlett” + fsm=TRUE failed
- lavPredict + newdata failed if newdata contained a single observation
- parallel= option did not work in boostrapLavaan()
- standardizedSolution + type = “std.lv” failed
- missing = “ml” (or “fiml”) + sampling.weights failed
- lavaan:::fsr() failed, unless missing = “listwise” was given explicitly
Version 0.6-5
- Released on CRAN: 28 Aug 2019
- New features and user-visible changes:
- a new option `effect.coding’ can be used to scale the latent variables;
a typical use is effect.coding = “loadings”, or
effect.coding = c(“loadings”, “intercepts”); if “loadings” is included,
equality constraints are used so that the average of the factor
loadings (per latent variable) equals 1; if “intercepts” is included,
equality constraints are used so that the sum of the intercepts (belonging
to the indicators of a single latent variable) equals zero; as a shortcut,
you can also set effect.coding = TRUE, which implies
effect.coding = c(“loadings”, “intercepts”);
note that his may not work well with bifactor models, or any other type
of model where items depend on multiple factors
- summary(fit, nd = 4) now shows 4 digits (after the decimal point) for
all (non-integer) numbers, including the header; the header has been
re-arranged slightly: the estimator is now shown on the top; the test
statistic(s) are now in a section ‘Model Test User Model:’
- the test= argument now accepts a vector of multiple test statistics,
for example test = c(“satorra.bentler”, “mean.var.adjusted”)
- parameterEstimates(), standardizedSolution() and fitMeasures() have a new
output= argument which can be set to “text” for pretty printing
- Known issues:
- Bugs/glitches discovered after the release:
- in the categorical setting (estimator U/WLSMV) + missing = “pairwise” + the number of thresholds is larger than one: some entries in the weight matrix
are not correct, resulting in (small) bias for some parameters
- optim.method=”none” is ignored in nlminb.constr() settings; as a
side-effect, this produces wrong results in lavTestLRT() if
method=”satorra.bentler.2010”, and explicit inequality constraints
are used in the model
- wrong labels for lavInspect(,”lv.mean”) and lavInspect(,”cov.all”) if
both formative and reflexive latent variables are used
- the “<~” operator did not work well in the categorical setting in
combination with conditional.x = TRUE
- parameterEstimates + fmi = TRUE often gives crazy results
- lavTestLRT + MLR + df=0 for one of the models results in an error
- estimator = “WLS” + continuous data + missing = “pairwise” does not
work
- loglikelood value if fixed.x = TRUE and only sample statistics are
provided is still reflecting the joint loglikelihood
Version 0.6-4
- Released on CRAN: 3 July 2019
- New features and user-visible changes:
- this release includes mostly changes under the hood
- an extra check is done for convergence (even if the optimizer claims
convergence): we check if all the elements of the (unscaled) gradient
are smaller than 0.0001 (in absolute value).
If not, we set converged = FALSE. The tolerance value
0.0001 can be changed by the option optim.dx.tol. To switch off this
check, use optim.dx.tol = +Inf
- lavInspect() gains new options: “vcov.def.joint” (and standardized
variants) to give the (joint) variance-covariance matrix of both the
free and `defined’ (using the := operator) variables;
“loglik.casewise” to extract casewise (log)likelihood values (only
if ML has been used);
“h1.information” to extract the information matrix of the
unrestricted h1 model
- lavTestScore() + uni table and modindices() output (in particular epc
and epv values) are now more alike
- lavPredict() + Bartlett now uses FIML to compute factor scores (in the
presence of missing data); new append.data= argument cbinds factor
scores and raw data; if assemble = TRUE, factor scores of multiple
groups will be joined in a single data.frame (with a group column);
accept newdata= argument, even if sample statistics were used when
fitting the original model
- using ordered = TRUE implies all variables should be treated as ordinal
- new logical arguments orthogonal.y and orthogonal.x can be used to specify
zero covariances between endogenous and exogenous latent variables (only)
respectively
- new option sampling.weights.normalization (set to “total” by default)
- group.equal now also accepts “composite.loadings” when the “<~”
operator is used
- parameterEstimates() gains a remove.nonfree= argument
- initial (but still experimental and undocumented) support for
rotation, EFA, and ESEM (contact me if you wish to test this)
- initial (but still experimental and undocumented) support for
the `Structural After Measurement’ (SAM) approach (see the new
lavaan:::sam() function; contact me if you wish to test this)
- Known issues:
- same as 0.6-1 (although many long standing github issues have been resolved)
- Bugs/glitches discovered after the release:
- twolevel models: standard errors are off for fixed effects (only) if the
model contains a regression of the form y ~ x, both variables are
observed, and x is not centered
- twolevel models: the chi-square test statistic for the baseline model
is wrong (too low): the chi-square test statistic for the full model
was substracted; therefore, if the user model fitted really bad, the
baseline test statistic was too low; if the user model fitted reasonably
well, there was (almost) no impact on the CFI/TLI fit measures
- lavPredict(): labels were wrong in the multigroup twolevel case
Version 0.6-3
- Released on CRAN: 22 September 2018
- New features and user-visible changes:
- new function lavResiduals() provides raw and standardized residuals
in addition to
summary statistics (rmr, srmr and crmr, including their standard error,
a test for exact fit, and an unbiased version);
for continuous data only (single-level, conditional.x = FALSE)
- new option missing = “ml.x” or missing = “fiml.x” will not delete
cases with missing values on exogenous covariates, even if fixed.x = TRUE
(this restores the behavior of < 0.6); this can be useful for models
with a large number of exogenous covariates, which you can treat as
stochastic, but where fixed.x = TRUE is just more convenient
- lavInspect/lavTech + “sampstat” now always returns the data summaries from
the h1 slot; this implies that if data is missing, and missing = “(fi)ml)”,
you get the ‘EM’ estimated covariance matrix and mean vector (instead
of the pairwise deleted covariance matrix from the samplestats slot)
- lavInspect/lavTech + “sampstat” and “implied” no longer return the mean
vector if meanstructure = FALSE
- srmr_bollen is renamed crmr in the output of fitMeasures(), and does no
longer count the (zero) diagonal elements when taking the average
- if conditional.x = TRUE, the baseline model
will now set the slopes free (instead of fixing them to zero); this
will usually result in a much better fit for the baseline model, and a
less optimistic value for CFI/TLI and friends; to get back the old
behaviour, set the option ‘baseline.conditional.x.free.slopes’ to FALSE
- Known issues:
- Bugs/glitches discovered after the release:
- mimic = “Mplus” was no longer setting meanstructure = TRUE
- if a partable was provided as input (instead of model syntax), the
`y’ variables were identified by using lavNames(fit, “ov.y”) instead
of lavNames(fit, “ov.nox”); therefore, we ‘missed’ some variables in
lav_dataframe_check_ordered(), not (automatically) treating them as
ordered
- mimic = “EQS” was not setting all the correct settings any longer
- lavPredict() + Bartlett + missing data did not produce ‘true’ FIML
factor scores (although they were very close)
- lav_partable_merge() did not set the group/level column right, affecting
lavTestLRT() when method = “SatorraBentler2010” (producing a warning
that the optimizer could not find a solution, and no test statistic)
- when a second-order factor was included in the model, the summary
output did not print a dot (‘.’, to indicate endogenous) in front of the
(residual) variances of the first-order latent variables
- lavTestLRT() + Satorra2000 with two models having the same df resulted
in a strange error
- lavTestScore() + uni resulted in epc values with the wrong sign; as a
result, the epv values were in the wrong direction
- lavaanList() produced “nlev too low for some vars” error, when ordered
variables were involved that included missing values (NA) (the NA was
counted as an additional category)
Version 0.6-2
- Released on CRAN: 16 July 2018
- New features and user-visible changes:
- cluster-robust standard errors are reported when the cluster= argument
is used in combination with a standard single-level syntax
(without the “level:” keywords); this can be used in combination with
missing = “fiml” (to handle missing values) and sampling weights
- added lower() and upper() modifiers in the model syntax; it works
in a similar way as the start() modifier to provide starting values;
for example,
to force a variance (say, y1 ~~ y1) to be larger than 0.001, you can
now write y ~~ lower(0.001)*y1
- even if the optimizer claims to have found a solution, we check if
the gradient is (almost) zero, and warn if not;
this check can be turned on/off by the option check.gradient = TRUE/FALSE
- more effort is done to check if the model is identified in the
presence of equality constraints; a warning is given if vcov is (nearly)
singular; this check can be turned on/off by the option
check.vcov = TRUE/FALSE
- header of the summary() function now shows the optimizer, the number
of free parameters, and the number of constraints (if any)
- fabin3 starting values for factor loadings are now also computed if
std.lv = TRUE
- Known issues:
- Bugs/glitches discovered after the release:
- ifi.scaled fit measure was not scaled
- lavTables() did not work if the first argument was a data.frame
- two-level + optim.method = “em” resulted in an error (about the check argument)
- modindices() did not work if conditional.x = TRUE
- lavInspect(, “data”) did not return covariates if conditional.x = TRUE
Version 0.6-1
- Released on CRAN: 22 May 2018
- New features and user-visible changes:
- initial support for two-level SEM with random intercepts; see
example(Demo.twolevel)
- initial support for sampling weights (for non-clustered data only for now)
- the code to compute (robust) standard errors and
(robust) test statistics has been rewritten; the code is now much more
consistent, but this may result in small changes in the values of some
robust test statistics as printed in the output of summary();
a meanstructure is no longer added automatically when switching to a
robust estimator
- conditional.x = FALSE now works in the categorical case (both with
estimators DWLS and PML)
- if fixed.x = TRUE, we compute the loglikelihood without the exogenous
covariates, and we do not allow for missing values in the exogenous
covariates when missing = “ml” (and fixed.x = TRUE)
- estimator = “PML” now works for continuous-only data, or mixed
continuous/ordinal data
- lavTestLRT(, method = “satorra2000”) which is the default when comparing
models that were fitted with estimator MLMV or WLSMV now uses the so-called
‘delta’ method by default; this allows for comparing models that are
nested in the covariance sense (and not just in the parameter sense);
in addition, a scaled.shifted test statistic will be used by default
- the warning about empty cells in bivariate cells (when
categorical data is used) is no longer shown
- many, many small changes under the hood
- Known issues:
- two-level SEM: no random slopes, no missing data, no categorical data
- the marginal ML infrastructure (estimator = “MML”) has not been updated yet
- several github issues have not been resolved yet
- Bugs/glitches discovered after the release:
- robust CFI/TLI and robust RMSEA values are printed as NA when
estimator = “MLR”
- lavPredict(, level = 2) does not handle phantom latent variables properly