Accounting for measurement error diminish fit

29 views
Skip to first unread message

Shajar

unread,
Aug 9, 2019, 2:10:23 AM8/9/19
to lavaan

Hi, in my research I started with a simple model without latent variables. I have put up a model that has a good fit (P-value = 0.696). But since I have knowledge of the measurement error, I wanted to put them in. I have defined each variable as a single- indicator that controls for measurement error – see code below. But the result is - no fit. I was expecting similar results, just distinguishing the measurement error from the structural error. Did I define the model correctly with regards to measurement error? If so, why is there such significant difference in the fit?

The code below contains connection to my data in google drive so you can replicate the issue.


### models with and without measurement error

# Load the data from a csv file I have put in google drive

id<-"1BQ0Q0QUYQdYRXNVxmfs92CIPWqCKlQ4S"# google file ID

dat<-read.csv(sprintf("https://docs.google.com/uc?id=%s&export=download",id),stringsAsFactors=FALSE)

 

library(lavaan)

 

### model a: simple model, no measurement error

mod.a <- '

NH4toTN ~ Crane_Count + Temp + pH_Outlet

Chl ~  season +  NH4toTN + pH_Outlet + Temp

TDP2TP ~  Crane_Count + Chl + Temp + Rain8d

'

# Fit model

mod.a.fit <- sem(mod.a, dat)

summary(mod.a.fit, rsq=TRUE, standardized=TRUE)

# Result: good fit. P-value = 0.696

 

### model b: same model but add measurement error

mod.b <- '

#latent variables

NH4toTN_L     =~ NH4toTN

Crane_Count_L =~ Crane_Count

Temp_L        =~ Temp

Chl_L         =~ Chl

pH_Outlet_L   =~ pH_Outlet

TDP2TP_L      =~ TDP2TP

 

#Regrression

NH4toTN_L ~ Crane_Count_L + Temp_L  + pH_Outlet_L

Chl_L ~  season +  NH4toTN_L + pH_Outlet_L + Temp_L

TDP2TP_L ~  Crane_Count_L + Chl_L + Temp_L + Rain8d

 

#fix error variances

NH4toTN     ~~ 0.507*NH4toTN

Crane_Count ~~ 0.146*Crane_Count

Temp        ~~ 0.034*Temp

Chl         ~~ 0.224*Chl

pH_Outlet   ~~ 0.031*pH_Outlet

TDP2TP      ~~ 0.399*TDP2TP

'

# Fit model

mod.b.fit <- sem(mod.b, dat)

summary(mod.b.fit, rsq=TRUE, standardized=TRUE)

# Result: no fit.

 

Terrence Jorgensen

unread,
Aug 9, 2019, 4:18:40 AM8/9/19
to lavaan
You can check the model-implied covariances

lavInspect(fit, "cov.ov")

and residuals

resid(fit)

to see how the models differ.

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


Shajar

unread,
Aug 9, 2019, 12:03:26 PM8/9/19
to lavaan
Thanks Terrence!
your suggestion helped me figure out the problem: I didn't apply the measurement error for 2 variables (season and Rain8d) because it is close to zero. Once I added the single indicator latent variable and defined the measurement error to be zero - everything falls into place... and the model has P-value=0.478.

Shajar

unread,
Aug 14, 2019, 3:12:22 PM8/14/19
to lavaan
I continue with my model but now I encounter a similar problem but different.
The model has composite variables. The model has good fit and df=6.
Now I take the exact same model and add the measurement error estimation as I did in the original question. But now the df= (-10).
I can't figure out why the addition of single factor latent variable and setting the error variance would change the df in the model.
It did not change the df on a model without composite variables. 
Where do I get it wrong?...

The model is a bit complex:

### model 1f: no measurement error
mod.1f <- '
# Latent variable  - composite
EndoP <~ 1*pH_Outlet  + pH_td_in + Temp + SunRad8d
ExoP  <~ 1*PP_td_in + Crane_Count

#Regrression
TDP2TP ~  EndoP + ExoP + Chl + Sh_TDP2TP
Chl ~  Sh_Chl + TDP2TP + EndoP 

EndoP ~~ 0*ExoP
EndoP ~~  2.36*EndoP
'
# Fit model
mod.1f.fit <- sem(mod.1f, dat1, estimator = "MLR")
# Examine model fit
fitMeasures(mod.1f.fit, c("chisq", "df", "pvalue","rmsea","cfi","srmr"))
summary(mod.1f.fit, rsq=TRUE, standardized=TRUE)
# good fit. df=6

# model 2f - add measurement error
mod.2f <- '
#latent variables for measurement error
L_TDP2TP      =~ TDP2TP
L_Chl              =~ Chl
L_pH_Outlet   =~ pH_Outlet
L_pH_td_in     =~ pH_td_in
L_Temp           =~ Temp
L_SunRad8d   =~ SunRad8d
L_PP_td_in      =~ PP_td_in
L_Crane_Count =~ Crane_Count
L_Sh_TDP2TP   =~ Sh_TDP2TP
L_Sh_Chl          =~ Sh_Chl

# Latent variable  - composite
EndoP <~ 1*L_pH_Outlet  + L_pH_td_in + L_Temp + L_SunRad8d
ExoP  <~ 1*L_PP_td_in + L_Crane_Count

#Regrression
L_TDP2TP ~  EndoP + ExoP + L_Chl + L_Sh_TDP2TP
L_Chl ~  L_Sh_Chl + L_TDP2TP + EndoP 
#Covariances
EndoP ~~ 0*ExoP
EndoP ~~  2.36*EndoP
#fix error variances
TDP2TP      ~~ 0.399*TDP2TP
Chl         ~~ 0.224*Chl
pH_Outlet   ~~ 0.031*pH_Outlet
pH_td_in    ~~ 0.602*pH_td_in
Temp        ~~ 0.034*Temp
SunRad8d    ~~ 0.013*SunRad8d
PP_td_in    ~~ 0.012*PP_td_in
Crane_Count ~~ 0.146*Crane_Count
Sh_TDP2TP   ~~ 0.345*Sh_TDP2TP
Sh_Chl      ~~ 0.212*Sh_Chl
'

# Fit model
mod.2f.fit <- sem(mod.2f, dat1, estimator = "MLR")
# Examine model fit and parameters
fitMeasures(mod.2f.fit, c("chisq", "df", "pvalue","rmsea","cfi","srmr"))
summary(mod.2f.fit, rsq=TRUE, standardized=TRUE)
# df= -10...

Terrence Jorgensen

unread,
Aug 14, 2019, 4:16:54 PM8/14/19
to lavaan
A composite is not a latent variable, and a formative construct is not a common factor (reflective construct).  The rules of identification are different.

Shajar

unread,
Aug 15, 2019, 10:38:17 AM8/15/19
to lavaan
Thanks Terrence,
I read some of the links you attached. Although there are some arguments against using composites I believe that it is right for my biogeochemical system. But even A.Diamantopoulos in "The error term in formative measurement models: interpretation and modeling implications" does not suggest how to model measurement error of each formative measure and relate to a model such as mine as "Spurious model" which I fail to understand why.
( Since this is not a lavaan issue but rather a general SEM - I will try SEMNET. )
Thanks again!
Reply all
Reply to author
Forward
0 new messages