Extract unstandardized factor loadings from one fit model and apply to another fit model

28 views
Skip to first unread message

christophe...@nicholls.edu

unread,
Jul 4, 2018, 5:16:27 PM7/4/18
to lavaan
Hi folks,

This is a rather complex request made in the spirit of both (1) reproducible workflows and (2) (to a related point) reducing the influence of human error.

The analysis that I'm running requires that I conduct two separate but related CFAs. The purpose of the first CFA is to estimate certain model parameters (e.g., unstandardized factor loadings and residual variances). Once these have been estimated, a subsequent baseline CFA is run whereby the aforementioned parameters are constrained to those values identified in in the first CFA. 

Here is some code to help you see what I'm trying to do:

CFA <–
'factor1 =~ x1 + x2 + x3
factor2 =~ x4 + x5 + x6
'
fit <– cfa(baseline)
summary(fit)

(note: "ufl" means "unstandardized factor loading"; "urv" means "unstandardized residual variance")

Baseline<–
'factor1 =~ ufl1*x1 + ufl2*x2 + ufl3*x3
factor2 =~ x4 + x5 + x6

#Constraint residual variances
 x1 ~~ urv1*x1
 x2 ~~ urv2*x2
 x3 ~~ urv3*x3
'

My question is simply this: how do I write a code that will extract the desired an place them into the lavaan model?

Thanks in advance for your help!

Chris

Terrence Jorgensen

unread,
Jul 9, 2018, 9:00:29 AM7/9/18
to lavaan
how do I write a code that will extract the desired an place them into the lavaan model?

You can use the parameter table from the first fitted model in place of the model syntax for the constrained model.

example(cfa)
PT
<- parTable(fit)
PT$free
<- 0
PT$start
<- PT$ustart <- PT$est
PT$user
<- 1
PT$SE
<- NULL
PT$est
<- NULL
fit
.constrained <- cfa(PT, data = HolzingerSwineford1939)
summary
(fit.constrained)

That constrains everything to your user-specified start values (which are the estimates from the first model).  If you only need to constrain the loadings are residual variances, you can write more conditional syntax to constrain only those rows of the parameter table.

Alternatively, you could loop over the parameter matrices to write syntax.  For example,

example(cfa)

(params <- lavInspect(fit, "est")) # list of 3 matrices in this 1-group example
obsnames
<- lavNames(fit, "ov")
latnames
<- lavNames(fit, "lv")
syntax
<- character(0)

## add factor loadings to syntax
for (ov in obsnames) {
 
for (lv in latnames) {
    est
<- params$lambda[ov, lv]
   
## optional, to omit unnecessary zeros:
   
# if (est == 0) next
    syntax
<- c(syntax, paste0(ov, " =~ ", est, "*", lv))
 
}
}


## add residual (co)variances to syntax
for (RR in seq_along(obsnames)) {
 
for (CC in RR:length(obsnames)) {
    est
<- params$theta[RR, CC]
   
## optional, to omit unnecessary zeros:
   
# if (est == 0) next
    syntax
<- c(syntax, paste0(obsnames[RR], " ~~ ", est, "*", obsnames[CC]))
 
}
}


## add latent (co)variances to syntax
for (RR in seq_along(latnames)) {
 
for (CC in RR:length(latnames)) {
    est
<- params$psi[RR, CC]
   
## optional, to omit unnecessary zeros:
   
# if (est == 0) next
    syntax
<- c(syntax, paste0(latnames[RR], " ~~ ", est, "*", latnames[CC]))
 
}
}


## check it
cat
(syntax, sep = "\n")


Terrence D. Jorgensen
Postdoctoral Researcher, Methods and Statistics
Research Institute for Child Development and Education, the University of Amsterdam

Reply all
Reply to author
Forward
0 new messages