Tom
Tom

Reputation: 2341

Creating complicated formula's with a function

I am using the following function to make formula's, where I can simply assign vector of variable names, where the function makes sure everything is in the right place and double variable names are excluded:

formula <- function(depvar, indepvars, instruments=NULL, othervars=NULL) {
    x <- c(indepvars, instruments, othervars)
    totvars <- unique(x)
    totvars <- x[!x %in% depvar]
    formula <- as.formula(
    paste(depvar, paste(totvars, collapse = " + "), sep = " ~ "))
    return(formula)
}
indepvars <- c("indepvarA", "indepvarB", "indepvarC")
instruments <- c("IV_A", "IV_B")
# lm
formula("depvar", indepvars)
# 1st stage - IV's for indepvarC
formula("indepvarC", indepvars, instruments)

However, I want the option to write a more complicated formula (an ivreg formula), namely:

depvar ~ instrumentedvar + indepvars | instrumentvars + indepvars

I have been trying the following:

formula <- function(depvar, indepvars, instruments=NULL, instrumentedvar=NULL, othervars=NULL, twostage=NULL) {
    x <- c(indepvars, instruments, othervars)
    totvars <- unique(x)
    totvars <- x[!x %in% depvar]
    if (is.null(twostage)) {
    formula <- as.formula(
    paste(depvar, paste(totvars, collapse = " + "), sep = " ~ "))
    } else {
    totvarsB <- totvars[!totvars %in% instrumentedvar]
    totvarsB <- c(as.character(totvarsB), as.character(instruments))
    formula <- as.formula(
      paste(depvar, paste(paste(totvars, collapse = " + "), paste("|", paste(totvarsB, collapse = " + " )), sep = " ~ ")))
    }
    return(formula)
}
indepvars <- c("indepvarA", "indepvarB", "indepvarC")
instruments <- c("IV_A", "IV_B")
instrumentedvar <- "indepvarC"
formula("indepvarC", indepvars, instruments, twostage=1)

But I cannot seem to get it right.

Upvotes: 1

Views: 53

Answers (1)

G. Grothendieck
G. Grothendieck

Reputation: 269501

Define reform which takes a vector of names and outputs a string in which they are connected with plus signs. Then use sprintf to generate the final string and convert that using as.formula:

reform <- function(x) paste(x, collapse = " + ")
makeFo <- function(lhs, rhs1, rhs2 = NULL, env = parent.frame()) {
  s <- sprintf("%s ~ %s", lhs, reform(c(rhs1, rhs2)))
  if (!missing(rhs2)) s <- sprintf("%s | %s", s, reform(rhs2))
  as.formula(s, env = env)
}

# test
makeFo("y", c("x1", "x2"))
## y ~ x1 + x2

makeFo("y", c("x1", "x2"), c("u1", "u2"))
## y ~ x1 + x2 + u1 + u2 | u1 + u2

Upvotes: 1

Related Questions