lavaan2emmeans | R Documentation |
emmeans
Support Functions for lavaan
ModelsProvide emmeans support for lavaan objects
recover_data.lavaan(object, lavaan.DV, ...) emm_basis.lavaan(object, trms, xlev, grid, lavaan.DV, ...)
object |
An object of class |
lavaan.DV |
|
... |
Further arguments passed to |
trms, xlev, grid |
See |
lavaan.DV
must be an endogenous variable, by appearing on
the left-hand side of either a regression operator ("~"
)
or an intercept operator ("~1"
), or both.
lavaan.DV
can also be a vector of endogenous variable, in which
case they will be treated by emmeans
as a multivariate outcome
(often, this indicates repeated measures) represented by an additional
factor named rep.meas
by default. The rep.meas=
argument
can be used to overwrite this default name.
This functionality does not support the following models:
Multi-level models are not supported.
Models not fit to a data.frame
(i.e., models fit to a
covariance matrix).
Fixed parameters (set with lavaan
's modifiers) are treated as-is:
their values are set by the users, and they have a SE of 0 (as such,
they do not co-vary with any other parameter).
If a multigroup model is supplied, a factor is added to the reference grid,
the name matching the group
argument supplied when fitting the model.
Note that you must set nesting = NULL
.
Limited testing suggests that these functions do work when the model was fit to incomplete data.
By default emmeans
recognizes binary variables (0,1) as a "factor"
with two levels (and not a continuous variable). With some clever contrast
defenitions it should be possible to get the desired emmeans / contasts.
See example below.
Mattan S. Ben-Shachar (Ben-Gurion University of the Negev; matanshm@post.bgu.ac.il)
## Not run: library(lavaan) library(emmeans) #### Moderation Analysis #### mean_sd <- function(x) mean(x) + c(-sd(x), 0, sd(x)) model <- ' # regressions Sepal.Length ~ b1 * Sepal.Width + b2 * Petal.Length + b3 * Sepal.Width:Petal.Length # define mean parameter label for centered math for use in simple slopes Sepal.Width ~ Sepal.Width.mean * 1 # define variance parameter label for centered math for use in simple slopes Sepal.Width ~~ Sepal.Width.var * Sepal.Width # simple slopes for condition effect SD.below := b2 + b3 * (Sepal.Width.mean - sqrt(Sepal.Width.var)) mean := b2 + b3 * (Sepal.Width.mean) SD.above := b2 + b3 * (Sepal.Width.mean + sqrt(Sepal.Width.var)) ' semFit <- sem(model = model, data = iris) ## Compare simple slopes # From `emtrends` test( emtrends(semFit, ~ Sepal.Width, "Petal.Length", lavaan.DV = "Sepal.Length", cov.red = mean_sd) ) # From lavaan parameterEstimates(semFit, output = "pretty")[13:15, ] # Identical slopes. # SEs differ due to lavaan estimating uncertainty of the mean / SD # of Sepal.Width, whereas emmeans uses the mean+-SD as is (fixed). #### Latent DV #### model <- ' LAT1 =~ Sepal.Length + Sepal.Width LAT1 ~ b1 * Petal.Width + 1 * Petal.Length Petal.Length ~ Petal.Length.mean * 1 V1 := 1 * Petal.Length.mean + 1 * b1 V2 := 1 * Petal.Length.mean + 2 * b1 ' semFit <- sem(model = model, data = iris, std.lv = TRUE) ## Compare emmeans # From emmeans test( emmeans(semFit, ~ Petal.Width, lavaan.DV = "LAT1", at = list(Petal.Width = 1:2)) ) # From lavaan parameterEstimates(semFit, output = "pretty")[15:16, ] # Identical means. # SEs differ due to lavaan estimating uncertainty of the mean # of Petal.Length, whereas emmeans uses the mean as is. #### Multi-Variate DV #### model <- ' ind60 =~ x1 + x2 + x3 # metric invariance dem60 =~ y1 + a*y2 + b*y3 + c*y4 dem65 =~ y5 + a*y6 + b*y7 + c*y8 # scalar invariance y1 + y5 ~ d*1 y2 + y6 ~ e*1 y3 + y7 ~ f*1 y4 + y8 ~ g*1 # regressions (slopes differ: interaction with time) dem60 ~ b1*ind60 dem65 ~ b2*ind60 + NA*1 + Mean.Diff*1 # residual correlations y1 ~~ y5 y2 ~~ y4 + y6 y3 ~~ y7 y4 ~~ y8 y6 ~~ y8 # conditional mean differences (besides mean(ind60) == 0) low := (-1*b2 + Mean.Diff) - (-1*b1) # 1 SD below M high := (b2 + Mean.Diff) - b1 # 1 SD above M ' semFit <- sem(model, data = PoliticalDemocracy) ## Compare contrasts # From emmeans emmeans(semFit, pairwise ~ rep.meas|ind60, lavaan.DV = c("dem60","dem65"), at = list(ind60 = c(-1,1)))[[2]] # From lavaan parameterEstimates(semFit, output = "pretty")[49:50, ] #### Multi Group #### model <- 'x1 ~ c(int1, int2)*1 + c(b1, b2)*ageyr diff_11 := (int2 + b2*11) - (int1 + b1*11) diff_13 := (int2 + b2*13) - (int1 + b1*13) diff_15 := (int2 + b2*15) - (int1 + b1*15) ' semFit <- sem(model, group = "school", data = HolzingerSwineford1939) ## Compare contrasts # From emmeans (note `nesting = NULL`) emmeans(semFit, pairwise ~ school | ageyr, lavaan.DV = "x1", at = list(ageyr = c(11, 13, 15)), nesting = NULL)[[2]] # From lavaan parameterEstimates(semFit, output = "pretty") #### Dealing with factors #### warpbreaks <- cbind(warpbreaks, model.matrix(~ wool + tension, data = warpbreaks)) model <- " # Split for convenience breaks ~ 1 breaks ~ woolB breaks ~ tensionM + tensionH breaks ~ woolB:tensionM + woolB:tensionH " semFit <- sem(model, warpbreaks) ## Compare contrasts # From lm -> emmeans lmFit <- lm(breaks ~ wool * tension, data = warpbreaks) lmEM <- emmeans(lmFit, ~ tension + wool) contrast(lmEM, method = data.frame(L_all = c(-1, .05, 0.5), M_H = c(0, 1, -1)), by = "wool") # From lavaan -> emmeans lavEM <- emmeans(semFit, ~ tensionM + tensionH + woolB, lavaan.DV = "breaks") contrast(lavEM, method = list( "L_all|A" = c(c(-1, .05, 0.5, 0), rep(0, 4)), "M_H |A" = c(c(0, 1, -1, 0), rep(0, 4)), "L_all|A" = c(rep(0, 4), c(-1, .05, 0.5, 0)), "M_H |A" = c(rep(0, 4), c(0, 1, -1, 0)) )) ## End(Not run)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.