Help! Testing partial measurement invariance with ordinal data (wlsmv est). lavaan/semTools

939 views
Skip to first unread message

Wessel van Eeden

unread,
Feb 21, 2015, 7:37:11 PM2/21/15
to lav...@googlegroups.com

I have a problem. I want to analyse the partial measurement invariance. I already analysed the measurement invariance by constraining the whole model. Now I want to constrain just one subfactor at a time. I think I do everything right, except when I do the semTool difftest R gives this error:

semTools:::difftest(config, weak)

 

Error in if (model1@Fit@test[[1]]df>model2@Fit@test[[1]]df) { : missing value where TRUE/FALSE needed

What am I doing wrong?  Im a R newby so I probably do something not right. Can annyone help me? This is my code:

library(lavaan)
library(semTools)
library(semPlot)

Dat192 = read.spss ("C:/Users/ACER/Desktop/Rfile/correct12.sav" , to.data.frame = T)

Datsub192 <- subset(Dat192, Time == "1" | Time == "2")

Datfit192 <- 'PDS =~ AGGR + AGOR + ANXI + COGN + MOOD + SOMA + SOPH
AGGR =~ SQ43 + SQ10 + SQ16 + SQ21
AGOR =~ SQ4 + SQ8 + SQ14 + SQ25
ANXI =~ SQ48 + SQ24 + SQ28 + SQ33 + SQ41 + SQ46
COGN =~ SQ2 + SQ6 + SQ39 + SQ44 + SQ47
MOOD =~ SQ13 + SQ7 + SQ3 + SQ19 + SQ38 + SQ40
SOMA =~ SQ31 + SQ5 + Q11 + SQ17 + SQ22 + SQ26 + SQ1
SOPH =~ SQ32 + SQ27 + SQ23 + SQ36 + SQ45 '

Datmodelfit192 <- cfa(Datfit192, data=Dat192, estimator="WLSMV", ordered=names(Dat192)[2:38], std.lv=TRUE , parameterization ="theta")

config <- cfa(Datfit192, data=Dat192, group= "Time", estimator="WLSMV", ordered=names(Dat192)[2:38], std.lv=TRUE , parameterization ="theta")

#everything group.partial except "SOPH"

weak <- cfa(Datfit192, data=Dat192, group= "Time", estimator="WLSMV", ordered=names(Dat192)[2:38], std.lv=TRUE , parameterization ="theta", group.equal = c("loadings"), group.partial=c(
"AGGR =~SQ43", "AGGR =~SQ10", "AGGR =~SQ16", "AGGR =~SQ21",
"AGOR =~SQ4" , "AGOR =~SQ8" , "AGOR =~SQ14" , "AGOR =~SQ25",
"ANXI =~SQ48", "ANXI =~SQ24", "ANXI =~SQ28", "ANXI =~SQ33", "ANXI =~SQ41", "ANXI =~SQ46",
"COGN =~SQ2", "COGN =~SQ6", "COGN =~SQ39", "COGN =~SQ44", "COGN =~SQ47",
"MOOD =~SQ13" , "MOOD =~SQ7", "MOOD =~SQ3", "MOOD =~SQ19" , "MOOD =~SQ38", "MOOD =~SQ40",
"SOMA =~SQ31" , "SOMA =~SQ5", "SOMA =~Q11" , "SOMA =~SQ17" , "SOMA =~SQ22" , "SOMA =~SQ26", "SOMA =~SQ1"))

semTools:::difftest(config, weak)

Alex Uzdavines

unread,
Feb 22, 2015, 10:37:14 AM2/22/15
to lav...@googlegroups.com
Just taking a swing at this without looking up the syntax, but are you missing a " = TRUE" for your weak option? Like, "(config, weak = TRUE)?

Terrence Jorgensen

unread,
Feb 23, 2015, 7:12:04 PM2/23/15
to lav...@googlegroups.com
Just taking a swing at this without looking up the syntax, but are you missing a " = TRUE" for your weak option? Like, "(config, weak = TRUE)?

No, the 2 arguments are (what should be) the two lavaan fitted model objects.  What's failing is the first line of the HIDDEN function "difftest" --

model1@Fit@test[[1]]$df > model2@Fit@test[[1]]$df

For some reason (not enough information provided), that is not producing a TRUE or FALSE.  But you don't need this hidden function to easily calculate the values it would return:

anova(config, weak) #or# lavTestLRT(config, weak)
fitMeasures(config, "cfi") - fitMeasures(weak, "cfi")
#or# 
fitMeasures(config, c("cfi","cfi.scaled")) - fitMeasures(weak, c("cfi","cfi.scaled"))


Terry

Wessel van Eeden

unread,
Feb 26, 2015, 4:45:43 AM2/26/15
to lav...@googlegroups.com
Thank you both so much for your help.
Altough it didnt work:\

> lavTestLRT(config, weak)
Chi Square Difference Test

         Df AIC BIC  Chisq Chisq diff Df diff Pr(>Chisq)
config 1244         8235.1                              
weak                                                    

> fitMeasures(config, "cfi") - fitMeasures(weak, "cfi")
Error in fitMeasures(weak, "cfi") : 
  lavaan ERROR: fit measures not available if model did not converge

> fitMeasures(config, c("cfi","cfi.scaled")) - fitMeasures(weak, c("cfi","cfi.scaled"))
Error in fitMeasures(weak, c("cfi", "cfi.scaled")) : 
  lavaan ERROR: fit measures not available if model did not converge

I think there is something wrong with:

weak <- cfa(Datfit192, data=Dat192, group= "Time", estimator="WLSMV", ordered=names(Dat192)[2:38], std.lv=TRUE , parameterization ="theta", group.equal = c("loadings"), group.partial=c( 
"AGGR =~SQ43", "AGGR =~SQ10", "AGGR =~SQ16", "AGGR =~SQ21", 
"AGOR =~SQ4" , "AGOR =~SQ8" , "AGOR =~SQ14" , "AGOR =~SQ25", 
"ANXI =~SQ48", "ANXI =~SQ24", "ANXI =~SQ28", "ANXI =~SQ33", "ANXI =~SQ41", "ANXI =~SQ46", 
"COGN =~SQ2", "COGN =~SQ6", "COGN =~SQ39", "COGN =~SQ44", "COGN =~SQ47", 
"MOOD =~SQ13" , "MOOD =~SQ7", "MOOD =~SQ3", "MOOD =~SQ19" , "MOOD =~SQ38", "MOOD =~SQ40", 
"SOMA =~SQ31" , "SOMA =~SQ5", "SOMA =~Q11" , "SOMA =~SQ17" , "SOMA =~SQ22" , "SOMA =~SQ26", "SOMA =~SQ1"))

altough I dont understand what. I checked it a hundred times.:(




Wessel van Eeden

unread,
Feb 26, 2015, 4:59:26 AM2/26/15
to lav...@googlegroups.com
I also tried this:

> Datfit192agor <- 'PDS =~ AGGR + AGOR + ANXI + COGN + MOOD + SOMA + SOPH
+ AGOR =~ SQ4 + SQ8 + SQ14 + SQ25
+ ANXI =~ SQ48 + SQ24 + SQ28 + SQ33 + SQ41 + SQ46
+ COGN =~ SQ2 + SQ6 + SQ39 + SQ44 + SQ47 
+ MOOD =~ SQ13 + SQ7 + SQ3 + SQ19 + SQ38 + SQ40
+ SOMA =~ SQ31 + SQ5 + Q11 + SQ17 + SQ22 + SQ26 + SQ1
+ SOPH =~ SQ32 + SQ27 + SQ23 + SQ36 + SQ45
+ AGGR =~ SQ43 + SQ10 + SQ16 + SQ21
+ AGOR ~ c(0,0)*1 
+ ANXI ~ c(NA,NA)*1
+ COGN ~ c(NA,NA)*1
+ MOOD ~ c(NA,NA)*1
+ SOMA ~ c(NA,NA)*1
+ SOPH ~ c(NA,NA)*1
+ AGGR ~ c(NA,NA)*1'

But then R gives this error: 

> Datmodelfit192agor <- cfa(Datfit192agor, data=Dat192, estimator="WLSMV", ordered=names(Dat192)[2:38], std.lv=TRUE , parameterization ="theta")
Error in getModifier(rhs[[2L]]) : 
  lavaan ERROR: can not parse modifier:cNANA

> config <- cfa(Datfit192agor, data=Dat192, group= "Time", estimator="WLSMV", ordered=names(Dat192)[2:38], std.lv=TRUE , parameterization ="theta")
Error in getModifier(rhs[[2L]]) : 
  lavaan ERROR: can not parse modifier:cNANA

:( please does anyone know what Im doing wrong here?

Terrence Jorgensen

unread,
Feb 26, 2015, 1:50:46 PM2/26/15
to lav...@googlegroups.com
Error in fitMeasures(weak, "cfi") : 
  lavaan ERROR: fit measures not available if model did not converge


OK, so the problem is just that you were trying to evaluate the fit of a model that didn't even converge?  It's good to know this is not a bug.  But it looks like we can add a check for convergence in the semTools:::difftest() function so the error message will be more informative.

 
weak <- cfa(Datfit192, data=Dat192, group= "Time", estimator="WLSMV", ordered=names(Dat192)[2:38], std.lv=TRUE , parameterization ="theta", group.equal = c("loadings"), group.partial=c( 
"AGGR =~SQ43", "AGGR =~SQ10", "AGGR =~SQ16", "AGGR =~SQ21", 
"AGOR =~SQ4" , "AGOR =~SQ8" , "AGOR =~SQ14" , "AGOR =~SQ25", 
"ANXI =~SQ48", "ANXI =~SQ24", "ANXI =~SQ28", "ANXI =~SQ33", "ANXI =~SQ41", "ANXI =~SQ46", 
"COGN =~SQ2", "COGN =~SQ6", "COGN =~SQ39", "COGN =~SQ44", "COGN =~SQ47", 
"MOOD =~SQ13" , "MOOD =~SQ7", "MOOD =~SQ3", "MOOD =~SQ19" , "MOOD =~SQ38", "MOOD =~SQ40", 
"SOMA =~SQ31" , "SOMA =~SQ5", "SOMA =~Q11" , "SOMA =~SQ17" , "SOMA =~SQ22" , "SOMA =~SQ26", "SOMA =~SQ1"))

altough I dont understand what. I checked it a hundred times.:(


You didn't provide the syntax "Datfit192" so it's hard to tell what went wrong.  Judging from the loadings specified in your follow-up post, it looks like you are constraining loadings to equality using the group.equal argument, but then freeing almost all of them using the group.partial argument.  If you have so few loadings to actually constrain across groups, why don't you just specify the few constraints with labels in the syntax?  Note that if there aren't enough constrained loadings for each construct, the model might not be identified if you were also allowing latent variance to be free (instead of fixing to 1 using "std.lv = TRUE") in the second group.

Terry



Wessel van Eeden

unread,
Feb 27, 2015, 10:58:16 AM2/27/15
to lav...@googlegroups.com
Thank you so much for you help.

Now I used labels to constrain the loading.

first base model:
Datsub272 <- subset(Dat272, Time == "1" | Time == "2")

Datfit272 <- 'Datsub272=~ AGGR + AGOR + ANXI + COGN + MOOD + SOMA + SOPH
AGOR =~ SQ4 + SQ8 + SQ14 + SQ25
ANXI =~ SQ48 + SQ24 + SQ28 + SQ33 + SQ41 + SQ46
COGN =~ SQ2 + SQ6 + SQ39 + SQ44 + SQ47 
MOOD =~ SQ13 + SQ7 + SQ3 + SQ19 + SQ38 + SQ40
SOMA =~ SQ31 + SQ5 + Q11 + SQ17 + SQ22 + SQ26 + SQ1
SOPH =~ SQ32 + SQ27 + SQ23 + SQ36 + SQ45
AGGR =~ SQ43 + SQ10 + SQ16 + SQ21'

Datmodelfit272 <- cfa(Datfit272, data=Dat272, estimator="WLSMV", ordered=names(Dat272)[2:38], std.lv=T , parameterization ="theta")
Config <- cfa(Datfit272, data=Dat272, groups="Time", estimator="WLSMV", ordered=names(Dat272)[2:38], std.lv=T , parameterization ="theta")

#AGOR loadings constraint

Datfit272agor<- 'Datsub272=~ AGGR + AGOR + ANXI + COGN + MOOD + SOMA + SOPH
AGOR =~ c(v4, v4)*SQ4 + c(v8, v8)*SQ8 +  c(v14, v14)*SQ14 + c(v25, v25)*SQ25
ANXI =~ SQ48 + SQ24 + SQ28 + SQ33 + SQ41 + SQ46
COGN =~ SQ2 + SQ6 + SQ39 + SQ44 + SQ47 
MOOD =~ SQ13 + SQ7 + SQ3 + SQ19 + SQ38 + SQ40
SOMA =~ SQ31 + SQ5 + Q11 + SQ17 + SQ22 + SQ26 + SQ1
SOPH =~ SQ32 + SQ27 + SQ23 + SQ36 + SQ45
AGGR =~ SQ43 + SQ10 + SQ16 + SQ21'

weakagor <- cfa(Datfit272agor, data=Dat272, group= "Time", estimator="WLSMV", ordered=names(Dat272)[2:38], std.lv=TRUE , parameterization ="theta")
semTools:::difftest(config, weakagor)

it all workst fine! Now I want to constrain thresholds and loadings (strong): 


Datfit272agorS<- 'Datsub272=~ AGGR + AGOR + ANXI + COGN + MOOD + SOMA + SOPH
AGOR =~ c(v4, v4)*SQ4 + c(v8, v8)*SQ8 +  c(v14, v14)*SQ14 + c(v25, v25)*SQ25
ANXI =~ SQ48 + SQ24 + SQ28 + SQ33 + SQ41 + SQ46
COGN =~ SQ2 + SQ6 + SQ39 + SQ44 + SQ47 
MOOD =~ SQ13 + SQ7 + SQ3 + SQ19 + SQ38 + SQ40
SOMA =~ SQ31 + SQ5 + Q11 + SQ17 + SQ22 + SQ26 + SQ1
SOPH =~ SQ32 + SQ27 + SQ23 + SQ36 + SQ45
AGGR =~ SQ43 + SQ10 + SQ16 + SQ21
SQ4 | c(th1,th1)*t1  
SQ4 | c(th2,th2)*t2
SQ4 | c(th3,th3)*t3  
SQ4 | c(th4,th4)*t4

SQ8 | c(th3,th3)*t1
SQ8 | c(th4,th4)*t2
SQ8 | c(th3,th3)*t3
SQ8 | c(th4,th4)*t4

SQ14 | c(th1,th1)*t5  
SQ14 | c(th2,th2)*t6
SQ14 | c(th3,th3)*t7  
SQ14 | c(th4,th4)*t8

SQ25 | c(th1,th1)*t9  
SQ25 | c(th2,th2)*t10
SQ25 | c(th3,th3)*t11 
SQ25 | c(th4,th4)*t12'

strongagor <- cfa(Datfit272agorS, data=Dat272, group= "Time", estimator="WLSMV", ordered=names(Dat272)[2:38], std.lv=TRUE , parameterization ="theta")

R gives me this error: Error in if (fx < 0) fx <- 0 : missing value where TRUE/FALSE needed

The weirdest thing is that I can constrain the threshold of two variables without a problem: 

Datfit272agorS<- 'Datsub272=~ AGGR + AGOR + ANXI + COGN + MOOD + SOMA + SOPH
AGOR =~ c(v4, v4)*SQ4 + c(v8, v8)*SQ8 +  c(v14, v14)*SQ14 + c(v25, v25)*SQ25
ANXI =~ SQ48 + SQ24 + SQ28 + SQ33 + SQ41 + SQ46
COGN =~ SQ2 + SQ6 + SQ39 + SQ44 + SQ47 
MOOD =~ SQ13 + SQ7 + SQ3 + SQ19 + SQ38 + SQ40
SOMA =~ SQ31 + SQ5 + Q11 + SQ17 + SQ22 + SQ26 + SQ1
SOPH =~ SQ32 + SQ27 + SQ23 + SQ36 + SQ45
AGGR =~ SQ43 + SQ10 + SQ16 + SQ21
SQ4 | c(th1,th1)*t1  
SQ4 | c(th2,th2)*t2
SQ4 | c(th3,th3)*t3  
SQ4 | c(th4,th4)*t4

SQ8 | c(th3,th3)*t1
SQ8 | c(th4,th4)*t2
SQ8 | c(th3,th3)*t3
SQ8 | c(th4,th4)*t4'

What does this mean? And how can I fix it?

Wessel van Eeden

unread,
Mar 1, 2015, 9:05:52 AM3/1/15
to lav...@googlegroups.com
Oops, now I see what I did wrong. I made a copy-paste mistake there. Sorry for that!
Reply all
Reply to author
Forward
0 new messages