使用 inspect() 报告的 Lavaan 不可信矩阵

Lavaan implausible matrices reported using inspect()

出于教学目的,我正在模拟与固定效应模型一致的数据,然后 运行 使用 lavaan 在 SEM 中模拟模型。我不明白 lavaan 使用 inspect() 函数给我的底层矩阵是怎么回事。

这是我出于再现性目的的协方差矩阵:

obs <- matrix( c( 2.1531960, 0.9219589, 1.1247727, 2.1399405, 1.6009631, 1.7877342,
                  0.9219589, 2.0183384, 1.1263892, 1.6586093, 2.0530063, 1.7664361,
                  1.1247727, 1.1263892, 1.9152931, 1.8183510, 1.7904083, 1.9676634,
                  2.1399405, 1.6586093, 1.8183510, 4.2225644, 3.0380404, 3.1018654,
                  1.6009631, 2.0530063, 1.7904083, 3.0380404, 4.0023862, 2.9819462,
                  1.7877342, 1.7664361, 1.9676634, 3.1018654, 2.9819462, 3.8469132), 
               nrow = 6, ncol = 6)

这是我的 lavaan 代码:

fe_sem <- '
# Define individual effects variable 
n =~ 1*y1 + 1*y2 + 1*y3 
# Regressions, constrain coefficient to be equal over time
y1 ~ b*x1
y2 ~ b*x2 
y3 ~ b*x3
# Allow unrestricted correlation between eta and covariates
n ~~ x1 + x2 + x3 
x1 ~~ x2 + x3
x2 ~~ x3 
# Constrain residual variances to be equal over time
y1 ~~ e*y1
y2 ~~ e*y2
y3 ~~ e*y3
'
fe_sem.fit <- sem( model = fe_sem, sample.cov = obs, sample.nobs = 300)

一切正常。鉴于我如何模拟数据,估计系数是正确的。我不明白的是 lavaan 是如何得到答案的。当我使用

inspect( fe_sem.fit)

lambda 矩阵是一个零矩阵:

## $lambda
##    n y1 y2 y3 x1 x2 x3
## y1 0  0  0  0  0  0  0
## y2 0  0  0  0  0  0  0
## y3 0  0  0  0  0  0  0
## x1 0  0  0  0  0  0  0
## x2 0  0  0  0  0  0  0
## x3 0  0  0  0  0  0  0

但我将潜在个体效应变量定义为 n =~ 1*y1 + 1*y2 + 1*y3,据我所知,lambda 矩阵应该如下所示:

## $lambda
##    n y1 y2 y3 x1 x2 x3
## y1 1  1  0  0  0  0  0
## y2 1  0  1  0  0  0  0
## y3 1  0  0  1  0  0  0
## x1 0  0  0  0  1  0  0
## x2 0  0  0  0  0  1  0
## x3 0  0  0  0  0  0  1

我已经手动仔细检查过这个。将 lambda 作为零矩阵会把一切都搞砸。有谁知道这里发生了什么?关于 lavaan 使用的矩阵符号,我有什么不明白的地方吗?

请注意 inspect 是一个较旧的函数,现在用作 lavInspect 的快捷方式。进一步注意矩阵的 dimnames。

library(lavaan)

obs <- matrix( c( 2.1531960, 0.9219589, 1.1247727, 2.1399405, 1.6009631, 1.7877342,
                  0.9219589, 2.0183384, 1.1263892, 1.6586093, 2.0530063, 1.7664361,
                  1.1247727, 1.1263892, 1.9152931, 1.8183510, 1.7904083, 1.9676634,
                  2.1399405, 1.6586093, 1.8183510, 4.2225644, 3.0380404, 3.1018654,
                  1.6009631, 2.0530063, 1.7904083, 3.0380404, 4.0023862, 2.9819462,
                  1.7877342, 1.7664361, 1.9676634, 3.1018654, 2.9819462, 3.8469132), 
               nrow = 6, ncol = 6, dimnames = list(NULL, c(paste0(rep(c("x", "y"), each = 3), 1:3)))
               )

lavInspect 的输出可以用默认为 "free" 的参数 what 来调节。也就是说,默认情况下,lavInspect 为您提供 free 参数——因为加载被限制为 1,所以没有自由参数。使用最基本的 MWE 版本你会得到

fe_sem <- "
# Define individual effects variable 
n =~ 1*y1 + 1*y2 + 1*y3 
"

fe_sem.fit <- sem( model = fe_sem, sample.cov = obs, sample.nobs = 300)
lavInspect(fe_sem.fit)$lambda

导致

##    n
## y1 0
## y2 0
## y3 0

您可以使用 what = "est".

访问 估计的 参数
lavInspect(fe_sem.fit, what = "est")$lambda

##    n
## y1 1
## y2 1
## y3 1

您可以使用 n =~ y1 + y2 + y3 交叉检查该行为。最后,随着回归语句的引入,y 变量成为内生变量而不是测量载荷。也就是说,对于 n 上的 "loadings",您需要查看 beta 矩阵。

fe_sem <- "
# Define individual effects variable 
n =~ 1*y1 + 1*y2 + 1*y3 
# Regressions, constrain coefficient to be equal over time
y1 ~ b*x1
y2 ~ b*x2 
y3 ~ b*x3
# Allow unrestricted correlation between eta and covariates
n ~~ x1 + x2 + x3 
x1 ~~ x2 + x3
x2 ~~ x3 
# Constrain residual variances to be equal over time
y1 ~~ e*y1
y2 ~~ e*y2
y3 ~~ e*y3
"
fe_sem.fit <- sem( model = fe_sem, sample.cov = obs, sample.nobs = 300)
lavInspect(fe_sem.fit, what = "est")$lambda

给你

##    n y1 y2 y3 x1 x2 x3
## y1 0  1  0  0  0  0  0
## y2 0  0  1  0  0  0  0
## y3 0  0  0  1  0  0  0
## x1 0  0  0  0  1  0  0
## x2 0  0  0  0  0  1  0
## x3 0  0  0  0  0  0  1

lavInspect(fe_sem.fit, what = "est")$beta

给你

##    n y1 y2 y3    x1    x2    x3
## n  0  0  0  0 0.000 0.000 0.000
## y1 1  0  0  0 0.326 0.000 0.000
## y2 1  0  0  0 0.000 0.326 0.000
## y3 1  0  0  0 0.000 0.000 0.326
## x1 0  0  0  0 0.000 0.000 0.000
## x2 0  0  0  0 0.000 0.000 0.000
## x3 0  0  0  0 0.000 0.000 0.000