我正在尝试运行 Lai 等人在 2021 年提出的以下函数,该函数旨在比较非嵌套模型与分类 AV 的拟合差异。模型如下所示:
Mod1 <- '
# Measurement models
# Predictor Variables
A =~ NoEPA2 + ChEPA2 + SvEPA2
N =~ NoEPN2 + ChEPN2 + SvEPN2
# Outcome Variables
I =~ DE_VORH + AN_VORH + AINTMAX
EX =~ C_VORH + O_VORH + AD_MAX
# Control variables
AGE =~ age
age ~~ 0*age
SEX =~ sex
sex ~~ 0*sex
EDU =~ edu
edu ~~ 0* edu
#Error correlation A, N, E
NoEPA1 ~~ NoEPN1
ChEPA1 ~~ ChEPN1
SvEPA1 ~~ SvEPN1
# Correlations DV
A ~~ N
I ~~ EX
# Paths
I ~ A + N + AGE + SEX + EDU
EX ~ A + N + AGE + SEX + EDU
'
Sem2 <- sem(Mod1,
data=a,
estimator = "WLSMV",
conditional.x = FALSE,
mimic = "Mplus",
ordered = c("DE_VORH", "AN_VORH","AINTMAX","O_VORH", "C_VORH","AD_MAX"))
summary(sem2,
fit.measures = TRUE,
standardize = TRUE,
rsquare = TRUE,
estimates = TRUE,
ci = FALSE)
Mod2 <- '
# Measurement models
# Predictor Variables
A =~ NoEPA1 + ChEPA1 + SvEPA1
N =~ NoEPN1 + ChEPN1 + SvEPN1
E =~ MxStEPEM + ChEPEM1 + SvEPEM1
# Outcome Variables
I =~ DE_VORH + AN_VORH + AINTMAX
EX =~ C_VORH + O_VORH + AD_MAX
# Control variables
AGE =~ age
age ~~ 0*age
SEX =~ sex
sex ~~ 0*sex
EDU =~ edu
edu ~~ 0* edu
#Error correlation A, N, E
NoEPA1 ~~ NoEPN1 + MxStEPEM
NoEPN1 ~~ MxStEPEM
ChEPA1 ~~ ChEPN1 + ChEPEM1
ChEPN1 ~~ ChEPEM1
SvEPA1 ~~ SvEPN1 + SvEPEM1
SvEPN1 ~~ SvEPEM1
# Correlations DV
A ~~ N + E
N ~~ E
I ~~ EX
# Paths
I ~ A + N + E + AGE + SEX + EDU
EX ~ A + N + E + AGE + SEX + EDU
'
sem3a <- sem(Mod2,
data=a,
estimator = "WLSMV",
conditional.x = FALSE,
mimic = "Mplus",
ordered = c("DE_VORH", "AN_VORH", "AINTMAX", "O_VORH","C_VORH","AD_MAX"))
summary(sem3a,
fit.measures = TRUE,
standardize = TRUE,
rsquare = TRUE,
estimates = TRUE,
ci = FALSE)
我要应用的功能如下所示:
## The function below returns point estimate and standard error for
## ∆RMSEA, ∆CFI, and ∆SRMR between two competing models A & B given categorical data.
## The two models do not need to be nested.
# fitA = Fitted 'lavaan' model object for Model A
# fitB = Fitted 'lavaan' model object for Model B
# fitZ = Fitted 'lavaan' model object for the baseline model for CFI
fit.diff.cat <- function(fitA, fitB){
######################################
# Internal functions
######################################
# Rearrange the model-implied correlation matrix of 'fitB' so that its columns and rows
# are in the same order as that in the model-implied correlation matrix of 'fitA'
rearrange.P.theta <- function(fitA, fitB){
R <- inspect(fitA, "sampstat")$'cov'
p <- dim(R)[1]
R <- as.matrix(R, p, p)
P.theta.A <- inspect(fitA, "cov.ov")
P.theta.B0 <- inspect(fitB, "cov.ov")
target.var.names <- rownames(R)
current.var.names <- rownames(P.theta.B0)
P.theta.B <- matrix(NA, p, p)
rownames(P.theta.B) <- colnames(P.theta.B) <- target.var.names
for (i.row in 1:p){
for(i.col in 1:p){
row.name <- target.var.names[i.row]
col.name <- target.var.names[i.col]
pick.row <- which(current.var.names==row.name)
pick.col <- which(current.var.names==col.name)
P.theta.B[i.row, i.col] <- P.theta.B0[pick.row, pick.col]
}
}
return(P.theta.B)
}# End of rearrange.P.theta()
# Rearrange the model-implied thresholds of 'fitB' so that its names
# are in the same order as that in the model-implied thresholds 'fitA'
rearrange.thresh <- function(fitA, fitB){
thresh <- inspect(fitA, "sampstat")$th
thresh.B0 <- inspect(fitB, "th")
target.var.names <- names(thresh)
current.var.names <- names(thresh.B0)
n.thresh <- length(thresh)
thresh.B <- rep(NA, n.thresh)
names(thresh.B) <- target.var.names
for (i in 1:n.thresh){
name <- target.var.names[i]
pick.name <- which(current.var.names==name)
thresh.B[i] <- thresh.B0[pick.name]
}
return(thresh.B)
}# End of rearrange.thresh()
# Rearrange the Delta matrix of 'fitB' so that its rows are
# in the same order as that in the Delta matrix of 'fitA'.
# Delta = derivative of P(theta) wrt theta
rearrange.Delta <- function(fitA, fitB){
Delta.B0 <- lavaan:::computeDelta(fitB@Model)[[1]]
n.theta <- dim(Delta.B0)[2]
thresh <- inspect(fitA, "sampstat")$th
thresh.B0 <- inspect(fitB, "th")
target.var.names <- names(thresh)
current.var.names <- names(thresh.B0)
n.thresh <- length(thresh)
Delta.th <- matrix(NA, n.thresh, n.theta)
rownames(Delta.th) <- target.var.names
for (i in 1:n.thresh){
name <- target.var.names[i]
pick.name <- which(current.var.names==name)
Delta.th[i,] <- Delta.B0[pick.name,]
}
P.theta.B0 <- inspect(fitB, "cov.ov")
R <- inspect(fitA, "sampstat")$'cov'
p <- dim(R)[1]
target.var.names <- rownames(R)
current.var.names <- rownames(P.theta.B0)
n.rho <- p*(p-1)/2
current.matrix <- matrix(NA, p, p)
current.matrix[lower.tri(current.matrix, diag=FALSE)] <- 1:n.rho
pick.vech <- rep(NA, n.rho)
j <- 1
for(i.col in 1:(p-1)){
for(i.row in (i.col+1):p){
row.name <- target.var.names[i.row]
col.name <- target.var.names[i.col]
pick.row <- which(current.var.names==row.name)
pick.col <- which(current.var.names==col.name)
if(pick.row >= pick.col) pick.vech[j] <- current.matrix[pick.row, pick.col]
if(pick.row < pick.col) pick.vech[j] <- current.matrix[pick.col, pick.row]
j <- j+1
}
}
Delta.rho <- matrix(NA, n.rho, n.theta)
for(i in 1:n.rho){
pick <- pick.vech[i] + n.thresh
Delta.rho[i,] <- Delta.B0[pick,]
}
Delta.B <- rbind(Delta.th, Delta.rho)
return(Delta.B)
}# End of rearrange.Delta()
######################################
# Main function
######################################
H.A <- inspect(fitA, "hessian")*2
H.B <- inspect(fitB, "hessian")*2
H.A.inv <- try(chol2inv(chol(H.A)), TRUE)
H.B.inv <- try(chol2inv(chol(H.B)), TRUE)
if(class(H.A.inv)=="matrix" & class(H.B.inv)=="matrix"){
n <- inspect(fitA, "nobs")
dA <- as.numeric(fitmeasures(fitA, "df"))
dB <- as.numeric(fitmeasures(fitB, "df"))
P.B <- rearrange.P.theta(fitA, fitB)
p <- dim(P.B)[1]
rho.B <- lav_matrix_vech(P.B, diagonal = FALSE)
thresh.B <- rearrange.thresh(fitA, fitB)
estB <- c(thresh.B, rho.B)
m <- inspect(fitA, "wls.obs")
estA <- inspect(fitA, "wls.est")
eA <- m - estA
eB <- m - estB
Gamma <- inspect(fitA, "gamma")
DeltaA <- lavaan:::computeDelta(fitA@Model)[[1]]
DeltaB <- rearrange.Delta(fitA, fitB)
p1 <- dim(DeltaA)[1]
g.A <- 2*t(eA)
K.A <- (-2)*t(DeltaA)
T.A <- 2*diag(1, p1)
Q.A <- T.A - t(K.A)%*%H.A.inv%*%K.A
G.A <- t(eA) %*% eA
G.A.bc0 <- G.A - sum(diag(Q.A%*%Gamma))/(2*n)
G.A.bc <- ifelse(G.A.bc0 < 0, 0, G.A.bc0)
g.B <- 2*t(eB)
K.B <- (-2)*t(DeltaB)
T.B <- 2*diag(1, p1)
Q.B <- T.B - t(K.B)%*%H.B.inv%*%K.B
G.B <- t(eB) %*% eB
G.B.bc0 <- G.B - sum(diag(Q.B%*%Gamma))/(2*n)
G.B.bc <- ifelse(G.B.bc0 < 0, 0, G.B.bc0)
R <- inspect(fitA, "sampstat")$cov
r <- lav_matrix_vech(R, diagonal = FALSE)
k <- length(r)
G.Z <- t(r) %*% r
G.Z.bc0 <- G.Z - sum(diag(Gamma))/n
G.Z.bc <- ifelse(G.Z.bc0 < 0, 0, G.Z.bc0)
G.A1 <- ifelse(G.A.bc > 0, G.A.bc, G.A)
G.B1 <- ifelse(G.B.bc > 0, G.B.bc, G.B)
G.Z1 <- ifelse(G.Z.bc > 0, G.Z.bc, G.Z)
## RMSEA diff
rmsea.AB <- sqrt(G.A.bc/dA) - sqrt(G.B.bc/dB)
J.rmsea.1 <- cbind( 1/(2*sqrt(dA*G.A1)), -1/(2*sqrt(dB*G.B1)) )
J.rmsea.2 <- rbind(g.A, g.B)
J.rmsea <- J.rmsea.1 %*% J.rmsea.2
var.rmsea.AB <- J.rmsea %*% Gamma %*% t(J.rmsea) / n
se.rmsea.AB <- sqrt(var.rmsea.AB)
## CFI diff
cfi.AB <- (G.B.bc - G.A.bc) / G.Z.bc
n.thresh <- length(fitted(fitA)$th)
r1 <- c(rep(0, n.thresh), r)
J.cfi.1 <- cbind( -1/G.Z1, 1/G.Z1, (G.A1-G.B1)/G.Z1^2 )
J.cfi.2 <- rbind(g.A, g.B, 2*t(r1) )
J.cfi <- J.cfi.1 %*% J.cfi.2
var.cfi.AB <- J.cfi %*% Gamma %*% t(J.cfi) / n
se.cfi.AB <- sqrt(var.cfi.AB)
## SRMR diff
srmr.AB <- sqrt(G.A.bc/k) - sqrt(G.B.bc/k)
J.srmr.1 <- cbind( 1/(2*sqrt(k*G.A1)), -1/(2*sqrt(k*G.B1)) )
J.srmr.2 <- rbind(g.A, g.B)
J.srmr <- J.srmr.1 %*% J.srmr.2
var.srmr.AB <- J.srmr %*% Gamma %*% t(J.srmr) / n
se.srmr.AB <- sqrt(var.srmr.AB)
#######
output <- c(rmsea.AB, se.rmsea.AB,
cfi.AB, se.cfi.AB,
srmr.AB, se.srmr.AB)
names(output) <- c("rmsea.AB", "se.rmsea.AB",
"cfi.AB", "se.cfi.AB",
"srmr.AB", "se.srmr.AB")
}# End of if Hessian is positive definite
else{output <- rep(NA, 6)}
return(output)
}
当我输入我的拟合模型时,返回以下错误:
P.theta.B[i.row, i.col] <- P.theta.B0[pick.row, pick.col] 中的错误:替换长度为零<
现在我尝试逐步运行命令,似乎这个错误是在运行此步骤的内部函数开始时产生的:
P.theta.B[i.row, i.col] <- P.theta.B0[pick.row, pick.col]
关于如何在那里进行故障排除的任何想法?我留下了很多问号。