5
.y5 2.351 0.480 4.895 0.000 2.351 0.347
.y6 4.954 0.914 5.419 0.000 4.954 0.443
.y7 3.431 0.713 4.814 0.000 3.431 0.322
.y8 3.254 0.695 4.685 0.000 3.254 0.315
ind60 0.448 0.087 5.173 0.000 1.000 1.000
.dem60 3.956 0.921 4.295 0.000 0.800 0.800
.dem65 0.172 0.215 0.803 0.422 0.039 0.039
可以看出sem()和cfa()这两个函数很相似,实际上,这两个函数现在几乎是一样的,但在将来可能发生变化。
在添加了standardized参数后,出现了Std.lv
, Std.all
两列,前者只有潜变量被标准化了,后者为所有变量都标准化了,也被称为“完全标准化解”。
6. 更多关于语法的内容
6.1 固定参数
对于一个对应4个指标的潜变量,lavaan默认将第一个指标的因子载荷固定为1,其他指标为自由。
但如果你有一个很好的理由来让所有因子载荷都固定为1,可以照如下做法:
f =~ y1 + 1*y2 + 1*y3 + 1*y4
一般来说,你需要通过给相关变量预先乘以一个数字来固定公式的参数,这个叫做“预乘机制”。
回想例1中的模型,默认3个潜变量两两相关。如果你想将某对变量的相关系数设为0,你需要为其添加一个协方差公式并将参数设为0.
在下面的语法中,除visual,textual间的协方差自由外,其他均设为0。并且我们希望固定speed的因子为一个单位,所以不需要设定第一个指标x7为1,因此我们给x7乘以NA使x7的因子载荷自由且未知,整个模型如下:
# three-factor model
visual =~ x1 + x2 + x3
textual =~ x4 + x5 + x6
speed =~ NA*x7 + x8 + x9
# orthogonal factors 正交因子
visual ~~ 0*speed
textual ~~ 0*speed
# fix variance of speed factor
speed ~~ 1*speed
你也可以用orthogonal = TRUE参数使所有潜变量正交,操作如下:
HS.model <- 'visual =~ x1 + x2 + x3
textual =~ x4 + x5 + x6
speed =~ x7 + x8 + x9'
fit.HS.ortho <- cfa(HS.model, data = HolzingerSwineford1939, orthogonal = TRUE)
相似的,你可以用std.lv = TRUE使所有潜变量的方差固定为一个单位:
HS.model <- 'visual =~ x1 + x2 + x3
textual =~ x4 + x5 + x6
speed =~ x7 + x8 + x9'
fit <- cfa(HS.model, data = HolzingerSwineford1939, std.lv = TRUE)
6.2 初值
lavaan包默认为自由参数自动生成初值,你也可以通过start()函数来自己设定初值,示例如下:
visual =~ x1 + start(0.8)*x2 + start(1.2)*x3
textual =~ x4 + start(0.5)x5 + start(1.0)x6
speed =~ x7 + start(0.7)x8 + start(1.8)x9
6.3 参数标签
我们也可以自己定义参数标签,标签不能以数字开头:
model <- '
# latent variable definitions
ind60 =~ x1 + x2 + myLabel*x3 #将ind60 =~ x3显示为myLabel
dem60 =~ y1 + y2 + y3 + y4
dem65 =~ y5 + y6 + y7 + y8
# regressions
dem60 ~ ind60
dem65 ~ ind60 + dem60
# residual (co)variances
y1 ~~ y5
y2 ~~ y4 + y6
y3 ~~ y7
y4 ~~ y8
y6 ~~ y8'
fit <- sem(model,
data = PoliticalDemocracy)
coef(fit)
结果如下:
6.4 修改器
我们预乘机制所使用的固定参数,修改初始值和参数标签等操作,都可以称为修改器,比如:
f =~ y1 + y2 + myLabel*y3 + start(0.5)*y3 + y4
#虽然y3项出现了两次,过滤器仍然会将y3作为一个指标对待
6.5 简单相等约束
有些情况我们会预设变量参数相等,可以用相同的label达到效果,也可以用equal()函数:
visual =~ x1 + v2*x2 + v2*x3
textual =~ x4 + x5 + x6
speed =~ x7 + x8 + x9
#或者用equal()
visual =~ x1 + x2 + equal("visual=~x2")*x3
textual =~ x4 + x5 + x6
speed =~ x7 + x8 + x9
6.6 非线性相等和不相等约束
假设有如下回归方程:
y ~ b1*x1 + b2*x2 + b3*x3
我们用随机数生成一个数据集,并用sem函数拟合:
set.seed(1234)
Data <- data.frame(y = rnorm(100),
x1 = rnorm(100),
x2 = rnorm(100),
x3 = rnorm(100))
model <- 'y ~ b1*x1 + b2*x2 + b3*x3'
fit <- sem(model, data = Data)
coef(fit)
结果为:
b1 b2 b3 y~~y
-0.052 0.084 0.139 0.970
如果我们想要为b1增加两个约束:\(b_1=(b_2+b_3)^2\) 和 \(b_1\ge\exp(b_2+b_3)\),操作如下:
model.constr <- '# model with labeled parameters
y ~ b1*x1 + b2*x2 + b3*x3
# constraints
b1 == (b2 + b3)^2
b1 > exp(b2 + b3)'
fit <- sem(model.constr, data = Data)
coef(fit)
结果如下:
b1 b2 b3 y~~y
0.495 -0.405 -0.299 1.610
7. 引入平均值
总的来说,结构方程用来模拟指标变量的协方差矩阵,但是在一些应用中,引入指标变量的均值也是有用的。一个方法是求助于截距项,使用如下所示的“截距公式”:
variable ~ 1
右边的1代表截距,比如在例1中,我们可以增加截距项到指标变量中:
# three-factor model
visual =~ x1 + x2 + x3
textual =~ x4 + x5 + x6
speed =~ x7 + x8 + x9
# intercepts
x1 ~ 1
x2 ~ 1
x3 ~ 1
x4 ~ 1
x5 ~ 1
x6 ~ 1
x7 ~ 1
x8 ~ 1
x9 ~ 1
然而还有一种更简单的方法:
fit <- cfa(HS.model,
data = HolzingerSwineford1939,
meanstructure = TRUE)
summary(fit)
结果如下:
lavaan (0.5-23.1097) converged normally after 35 itera