an error when running configural invariance analysis

4 replies [Last post]
Yunfei Wu's picture
Offline
Joined: 03/03/2010

I was trying to run a piece of code to measure MEBS (30 items) across gender and I got an error message which says: "Error: The job for model 'Moderated FI Model' exited abnormally with the error message: Expected covariance matrix is not positive-definite in row 0.".

I was trying to change the starting values (say, by making all of the covariances and free regressions .5) by taking suggestion posed on the forum and got the same error message. Does anyone can help on this? Thanks.

Yunfei

-------------the code ---------------
options(width=110)
library(psych)
library(OpenMx)
heritage <- read.table("heritage.csv", sep=',', header=TRUE, na.strings=c(9999, 9998))

# look at summaries of each of the data columns
summary(heritage)

# The describe() function doesn't like dates, so we find the number of columns
# and don't pass the last three columns to describe.
dim(heritage)
describe(heritage[,1:47])

heritageFrame <- data.frame(y1=heritage$q1er,
y2=heritage$q2er,
y3=heritage$q3er,
y4=heritage$q4er,
y5=heritage$q5er,
y6=heritage$q6er,
y7=heritage$q7er,
y8=heritage$q8er,
y9=heritage$q9er,
y10=heritage$q10er,
y11=heritage$q11er,
y12=heritage$q12er,
y13=heritage$q13er,
y14=heritage$q14er,
y15=heritage$q15er,
y16=heritage$q16er,
y17=heritage$q17er,
y18=heritage$q18er,
y19=heritage$q19er,
y20=heritage$q20er,
y21=heritage$q21er,
y22=heritage$q22er,
y23=heritage$q23er,
y24=heritage$q24er,
y25=heritage$q25er,
y26=heritage$q26er,
y27=heritage$q27er,
y28=heritage$q28er,
y29=heritage$q29er,
y30=heritage$q30er,
female=heritage$gender)

describe(heritageFrame)

indicatorsY <- paste("y", 1:30, sep="")
covariates <- c("female")
latentsY <- c("F1")

# ----------------------------------
# Moderated FI
# Configural FI: Now set up configural FI model.
# Reference standardization is variance=1 & mean=0 for moderator=0 condition.
#
dummies <- c("d_L1", "d_L2", "d_L3", "d_L4", "d_L5", "d_L6", "d_L7", "d_L8","d_L9","d_L10",
"d_L11","d_L12","d_L13","d_L14","d_L15","d_L16","d_L17","d_L18","d_L19","d_L20",
"d_L21","d_L22","d_L23","d_L24","d_L25","d_L26","d_L27","d_L28","d_L29","d_L30")
dum_F <- c("d_F1")
dum_Fv <- c("d_F1v")
dum_Fi <- c("d_i1", "d_i2", "d_i3", "d_i4", "d_i5", "d_i6", "d_i7", "d_i8","d_i9","d_i10",
"d_i11","d_i12","d_i13","d_i14","d_i15","d_i16","d_i17","d_i18","d_i19","d_i20",
"d_i21","d_i22","d_i23","d_i24","d_i25","d_i26","d_i27","d_i28","d_i29","d_i30")
dum_Fr <- c("d_r1", "d_r2", "d_r3", "d_r4", "d_r5", "d_r6", "d_r7", "d_r8","d_r9","d_r10",
"d_r11","d_r12","d_r13","d_r14","d_r15","d_r16","d_r17","d_r18","d_r19","d_r20",
"d_r21","d_r22","d_r23","d_r24","d_r25","d_r26","d_r27","d_r28","d_r29","d_r30")

FactorConfigFI <- mxModel("Moderated FI Model", type="RAM",
manifestVars=c(indicatorsY),
latentVars=c(latentsY, dummies, dum_F, dum_Fv, dum_Fi, dum_Fr),

# Fix the factor mean for free estimation of intercepts (structural)
mxPath(from="one", to=c(latentsY), arrows=1, free=FALSE, values=0),

# Moderate the factor variance (structural; variance fixed to 1 for moderater=0 reference)
mxPath(from=c(latentsY), arrows=2, free=FALSE, values=1, labels="varF1"),
mxPath(from=dum_Fv, to=c(latentsY), arrows=1, free=TRUE, values=1),
mxPath(from=c(latentsY), to=dum_Fv, arrows=1, free=FALSE, labels="data.female"),
mxPath(from=dum_Fv, arrows=2, free=FALSE, values=0),

mxData(heritageFrame, type="raw")
)

FactorConfigFIout <- mxRun(FactorConfigFI)
summary(FactorConfigFIout)

Ryne's picture
Offline
Joined: 07/31/2009
None of your paths relate to

None of your paths relate to any of your observed variables. Thus, the model you've specified creates an expected covariance matrix of all zeros, which is not positive-definite. You'll have to add factor loadings, residual variance and mean terms for the manifest variables to test for any kind of invariance.

Also keep in mind that your unlabeled free parameter that represents the female variance will be added to the male variance, and thus can take any value above -1 (-male variance). Representing that parameter as the variance of dum_Fv rather than a second one-headed arrow is both clearer and saves you a line of code.

Yunfei Wu's picture
Offline
Joined: 03/03/2010
Thanks Ryne! I have

Thanks Ryne! I have re-modified the code and added factor loadings, residual variance and means terms for the manifest variables to test the invariance. I got an error message that "Error: The job for model 'Moderated FI Model' exited abnormally with the error message: Attempted to invert non-invertable matrix.". How to deal with this?
By the way, I don't understand your last sentence of the comments "Representing that parameter as the variance of dum_Fv rather than a second one-headed arrow is both clearer and saves you a line of code.". Can you explain more specifically? Thanks.

Attached is the new code. ---------------------------

heritage <- read.table("heritage.csv", sep=',', header=TRUE, na.strings=c(9999, 9998))

# look at summaries of each of the data columns

summary(heritage)

dim(heritage)
describe(heritage[,1:47])

heritageFrame <- data.frame(y1=heritage$q1er,
y2=heritage$q2er,
y3=heritage$q3er,
y4=heritage$q4er,
y5=heritage$q5er,
y6=heritage$q6er,
y7=heritage$q7er,
y8=heritage$q8er,
y9=heritage$q9er,
y10=heritage$q10er,
y11=heritage$q11er,
y12=heritage$q12er,
y13=heritage$q13er,
y14=heritage$q14er,
y15=heritage$q15er,
y16=heritage$q16er,
y17=heritage$q17er,
y18=heritage$q18er,
y19=heritage$q19er,
y20=heritage$q20er,
y21=heritage$q21er,
y22=heritage$q22er,
y23=heritage$q23er,
y24=heritage$q24er,
y25=heritage$q25er,
y26=heritage$q26er,
y27=heritage$q27er,
y28=heritage$q28er,
y29=heritage$q29er,
y30=heritage$q30er,
female=heritage$gender)

describe(heritageFrame)

indicatorsY <- paste("y", 1:30, sep="")
covariates <- c("female")
latentsY <- c("F1")

# ----------------------------------
# Moderated FI
# Configural FI: Now set up configural FI model.
# Reference standardization is variance=1 & mean=0 for moderator=0 condition.
#
dummies <- c("d_L1", "d_L2", "d_L3", "d_L4", "d_L5", "d_L6", "d_L7", "d_L8","d_L9","d_L10",
"d_L11","d_L12","d_L13","d_L14","d_L15","d_L16","d_L17","d_L18","d_L19","d_L20",
"d_L21","d_L22","d_L23","d_L24","d_L25","d_L26","d_L27","d_L28","d_L29","d_L30")
dum_F <- c("d_F1")
dum_Fv <- c("d_F1v")
dum_Fi <- c("d_i1", "d_i2", "d_i3", "d_i4", "d_i5", "d_i6", "d_i7", "d_i8","d_i9","d_i10",
"d_i11","d_i12","d_i13","d_i14","d_i15","d_i16","d_i17","d_i18","d_i19","d_i20",
"d_i21","d_i22","d_i23","d_i24","d_i25","d_i26","d_i27","d_i28","d_i29","d_i30")
dum_Fr <- c("d_r1", "d_r2", "d_r3", "d_r4", "d_r5", "d_r6", "d_r7", "d_r8","d_r9","d_r10",
"d_r11","d_r12","d_r13","d_r14","d_r15","d_r16","d_r17","d_r18","d_r19","d_r20",
"d_r21","d_r22","d_r23","d_r24","d_r25","d_r26","d_r27","d_r28","d_r29","d_r30")

FactorConfigFI <- mxModel("Moderated FI Model", type="RAM",
manifestVars=c(indicatorsY),
latentVars=c(latentsY, dummies, dum_F, dum_Fv, dum_Fi, dum_Fr),

# Fix the factor mean for free estimation of intercepts (structural)
mxPath(from="one", to=c(latentsY), arrows=1, free=TRUE, values=0.5),

# Moderate the factor variance (structural; variance fixed to 1 for moderater=0 reference)
mxPath(from=c(latentsY), arrows=2, free=FALSE, values=1, labels="varF1"),
mxPath(from=dum_Fv, to=c(latentsY), arrows=1, free=TRUE, values=0.5),
mxPath(from=c(latentsY), to=dum_Fv, arrows=1, free=FALSE, labels="data.female"),
mxPath(from=dum_Fv, arrows=2, free=FALSE, values=0),

# Moderate the factor loadings
mxPath(from=c(latentsY), to=indicatorsY, arrows=1, free=TRUE, values=.8),
mxPath(from=dummies, to=c(indicatorsY), arrows=1, free=TRUE, values=.2),
mxPath(from=c(latentsY), to=dummies, arrows=1, free=FALSE, labels="data.female"),
mxPath(from=dummies, arrows=2, free=FALSE, values=0),

# Moderate the intercepts
mxPath(from="one", to=c(indicatorsY), arrows=1, free=TRUE, values=1),
mxPath(from="one", to=dum_Fi, arrows=1, free=TRUE, values=1),
mxPath(from=dum_Fi, to=c(indicatorsY), arrows=1, free=FALSE, labels="data.female"),

# Moderate the residual variances
mxPath(from=c(indicatorsY), arrows=2, free=TRUE, values=.8,
labels=c("e1","e2","e3","e4","e5","e6","e7","e8","e9","e10",
"e11","e12","e13","e14","e15","e16","e17","e18","e19","e20",
"e21","e22","e23","e24","e25","e26","e27","e28","e29","e30")),
mxPath(from=dum_Fr, to=c(indicatorsY), arrows=1, free=TRUE, values=1),
mxPath(from=c(indicatorsY), to=dum_Fr, arrows=1, free=FALSE, labels="data.female" ),
mxPath(from=dum_Fr, arrows=2, free=FALSE, values=0),

mxData(heritageFrame, type="raw")
)

FactorConfigFIout <- mxRun(FactorConfigFI)

Ryne's picture
Offline
Joined: 07/31/2009
Regarding my earlier comment,

Regarding my earlier comment, all of the dummy variables get very confusing, both for people who are just starting on the code and for your interpretation. You may be better off long-term by specifying this as a multiple group model, with one group for males and one for females, as you have 91 dummy variables and 30 manifest variables. If you're not going to specify this as a multiple group model, then you should recognize that your new parameter isn't the female variance, but rather a statement about the difference in variances between males and females. Giving your dummy variable a variance equal to the definition variable and having it predict latentsY with weight 1 is slightly clearer.

You say you're fixing the factor mean at zero, but you're actually letting it be freely estimated with a starting value of 0.5. This is certainly a major problem, as you're also estimating all intercepts as well.

For future reference, attach a file using the 'file attachments' tab below rather than copy and pasting in code; R doesn't always read website text well due to line breaks and other web formatting.

tbates's picture
Offline
Joined: 07/31/2009
Often the non-invertable

Often the non-invertable matrix error arises when start values are identical. Try jiggling them a bit around your reasonable start value.

try either spelling them out, or let R do it for you with rnorm(n,start,.05) where n is how many paths you are starting, start is the mean value you want, and .05 is an SD of jiggle to (hopefully) stop the matrix being invertable.