reformulate handles this problem quite naturally, though how you would apply it is context-dependent.
If you want to drop interactions of order greater than order_max from an existing formula, then you can do:
f1 <- function(formula, order_max) {
a <- attributes(terms(formula))
reformulate(termlabels = a$term.labels[a$order <= order_max],
response = if (r <- a$response) a$variables[[1L + r]],
intercept = a$intercept,
env = environment(formula))
}
f1(y ~ a * b * c * d * e, 2L)
## y ~ a + b + c + d + e + a:b + a:c + b:c + a:d + b:d + c:d + a:e +
## b:e + c:e + d:e
If you have a character vector x listing names of variables, and you want to construct a formula containing their interactions up to order order_max, then you can do:
Edit: Never mind - follow @RitchieSacramento's suggestion and use the ^ operator in this case.
f2 <- function(x, order_max, response = NULL, intercept = TRUE, env = parent.frame()) {
paste1 <- function(x) paste0(x, collapse = ":")
combn1 <- function(n) if (n > 1L) combn(x, n, paste1) else x
termlabels <- unlist(lapply(seq_len(order_max), combn1), FALSE, FALSE)
reformulate(termlabels = termlabels, response = response,
intercept = intercept, env = env)
}
f2(letters[1:5], 2L, response = quote(y))
## y ~ a + b + c + d + e + a:b + a:c + a:d + a:e + b:c + b:d + b:e +
## c:d + c:e + d:e
To be parsed correctly, nonsyntactic variable names must be protected with backquotes:
f2(c("`!`", "`?`"), 1L, response = quote(`#`))
## `#` ~ `!` + `?`