Is there a way to create an R function using a string formula with ', and " =~"?

Viewed 262

I'm trying to create an R function that lets me specify latent variables and indicators. Is there a way to convert the following three code lines into a function?

            ' visual  =~ x1 + x2 + x3 
              textual =~ x4 + x5 + x6
              speed   =~ x7 + x8 + x9 '

I tried using paste and paste0 but it didn't work very well. For example, using just one latent variable, I tried this:

myFunction <- function(z, x, ...) {
  latent_variable   <- paste0(x)
  latent_indicators <- paste0(..., collapse = " + ")
  latent_formula <- paste0(" ' ", latent_variable, "=", "~", latent_indicators, " ' ")
  
  fit <- cfa(latent_formula, data = z)
  
  summary(fit, fit.measures=TRUE)
}

myFunction(HolzingerSwineford1939, "visual", c("x1", "x2", "x3"))

But I'm getting this error:

Error in lavParseModelString(model) : lavaan ERROR: left hand side (lhs) of this formula: 'visual =~ x1+x2+x3' contains either a reserved word (in R) or an illegal character: “'visual” See ?reserved for a list of reserved words in R Please use a variable name that is not a reserved word in R and use only characters, digits, or the dot symbol.

To give more context, this is where the function will be used. Please see code below:

library(lavaan)
library(lavaanPlot)

HS.model <- ' visual  =~ x1 + x2 + x3 
              textual =~ x4 + x5 + x6
              speed   =~ x7 + x8 + x9 '

fit <- cfa(HS.model, data=HolzingerSwineford1939)

summary(fit, fit.measures=TRUE)
        
lavaanPlot(model = fit)

Any help will be appreciated. Thank you for your time.

1 Answers

You should not be pasting the single quotes into your formula. You are building the string already with paste(). Just use

latent_formula <- paste0(latent_variable, "=", "~", latent_indicators)

If you wanted to combine more than one responts, here's a function that will generate that formula

myFunction <- function(...) {
  params <- list(...)
  stopifnot(length(params)%%2==0)
  lefts = params[seq(1,length(params), by=2)]
  rights = params[seq(2,length(params), by=2)]
  rights <- Map(paste, rights, collapse="+")
  paste(paste0(lefts, " =~", rights), collapse="\n")
}

myFunction("visual", c("x1", "x2", "x3"), "textual", c("x4", "x5", "x6"), "speed", c("x7", "x8", "x9"))
Related