Xian Zhao
Xian Zhao

Reputation: 81

Loop with Lavaan in R couldn't find the variable

I was running the following code so that my Lavaan Model can test different predictors. However, the error says it couldn't find my "predictor". I need to keep that "paste" row so that I can specify whether it is a ".x" or ".y" variable. I feel it's a simple question. Can someone please help me out? Thanks!

gender_thermometer.x <-sample(0:10, 1000, rep = TRUE)
gender_thermometer.y <-sample(0:10, 1000, rep = TRUE)
COVID_threat.x <-sample(0:10, 1000, rep = TRUE)
COVID_threat.y <-sample(0:10, 1000, rep = TRUE)
d_exhaustion.x <-sample(0:10, 1000, rep = TRUE)
d_relaxation.x <-sample(0:10, 1000, rep = TRUE)
d_not_sharing_negative.x <-sample(0:1, 1000, rep = TRUE)
Couple_ID <-sample(0:100, 1000, rep = TRUE)
data_wide<-data.frame(gender_thermometer.x,gender_thermometer.y,COVID_threat.x,COVID_threat.y,
                      d_exhaustion.x,d_relaxation.x,d_not_sharing_negative.x,Couple_ID)

library(lavaan)
models <- list()

for (i in c( "gender_thermometer","COVID_threat")) {
  
  print(paste0("###################:",i))
  predictor= paste(i,".y",sep = "")
  
  model[[i]] <- '
    level: 1
        d_exhaustion.x ~ b1*d_relaxation.x + c1*d_not_sharing_negative.x + predictor
        d_relaxation.x ~ a1*d_not_sharing_negative.x + predictor
        d_not_sharing_negative.x~f1*predictor
        indirect1:=f1*a1*b1
        indirect11:=f1*c1
    level: 2
        d_exhaustion.x ~ b2*d_relaxation.x + c2*d_not_sharing_negative.x + predictor
        d_relaxation.x ~ a2*d_not_sharing_negative.x + predictor
        d_not_sharing_negative.x~f2*predictor
        indirect2:=f2*a2*b2
        indirect22:=f2*c2
        
'
  
  fit[[i]] <- sem(model = model[[i]], data = data_wide, cluster = "Couple_ID")
  print(summary(fit[[i]]))
}

Error in lav_data_full(data = data, group = group, cluster = cluster, : lavaan ERROR: missing observed variables in dataset: predictor

Upvotes: 0

Views: 134

Answers (1)

Parfait
Parfait

Reputation: 107652

R string formatting requires interpolation handlers like sprintf or paste like you do in assigning predictor. Currently, the model string takes literal predictor and not its underlying value.

So, consider string formatting such as with sprintf (wrapper to C function):

vars <- c("gender_thermometer", "COVID_threat")
models <- vector(mode="list", length=length(vars))

for (i in seq_along(vars)) {  
  print(paste0("###################:", vars[[i]]))
  predictor <- paste0(vars[[i]], ".y")
  
  # STRING WITH %1$s PLACEHOLDERS
  model_string <- '
    level: 1
        d_exhaustion.x ~ b1*d_relaxation.x + c1*d_not_sharing_negative.x + %1$s
        d_relaxation.x ~ a1*d_not_sharing_negative.x + %1$s
        d_not_sharing_negative.x~f1*%1$s
        indirect1:=f1*a1*b1
        indirect11:=f1*c1
    level: 2
        d_exhaustion.x ~ b2*d_relaxation.x + c2*d_not_sharing_negative.x + %1$s
        d_relaxation.x ~ a2*d_not_sharing_negative.x + %1$s
        d_not_sharing_negative.x~f2*%1$s
        indirect2:=f2*a2*b2
        indirect22:=f2*c2
  '
  
  # FORMAT STRING WITH VALUE
  models[[i]] <- sprintf(model_string, predictor)
  cat(models[[i]])

  fit[[i]] <- sem(model = models[[i]], data = data_wide, cluster = "Couple_ID")

  print(summary(fit[[i]]))
}

Alternatively with gsub, replacing literal predictor with variable value:

model_string <- '
    level: 1
        d_exhaustion.x ~ b1*d_relaxation.x + c1*d_not_sharing_negative.x + predictor
        d_relaxation.x ~ a1*d_not_sharing_negative.x + predictor
        d_not_sharing_negative.x~f1*predictor
        indirect1:=f1*a1*b1
        indirect11:=f1*c1
    level: 2
        d_exhaustion.x ~ b2*d_relaxation.x + c2*d_not_sharing_negative.x + predictor
        d_relaxation.x ~ a2*d_not_sharing_negative.x + predictor
        d_not_sharing_negative.x~f2*predictor
        indirect2:=f2*a2*b2
        indirect22:=f2*c2
'

models[[i]] <- gsub("predictor", predictor, model_string)

Upvotes: 0

Related Questions