I'm trying to paste a formula together to run in a model but I run into problems when I try to incorporate the random-effects. I want to define the random-effects separately and then add to the formula.
Simple working example without as.formula
:
library(INLA)
data(Epil)
head(Epil)
##Define the model
formulae = y ~ Trt + Age + V4 + f(Ind, model = "iid") + f(rand, model = "iid")
formulae
# y ~ Trt + Age + V4 + f(Ind, model = "iid") + f(rand, model = "iid")
#WORKS
result = inla(formulae, family = "poisson", data = Epil, control.predictor = list(compute = TRUE))
Now if I want to make this more flexible where I can change the random-effects between models but not change the fixed effects, I tried something like this using as.formula
:
test_vars = c("Trt", "Age", "V4")
mm <- quote(
f(Ind, model = 'iid') + f(rand, model = "iid")
)
mm
formula_2 <- as.formula(paste("y ~", paste(paste(test_vars, collapse = "+"), "+", mm)))
formula_2 #wont work here as expected
# y ~ Trt + Age + V4 + +y ~ Trt + Age + V4 + f(Ind, model = "iid")
formula_2 <- as.formula(paste("y ~", paste(paste(test_vars, collapse = "+"), "+", parse(text = mm))))
formula_2 #missing + f(rand, model = "iid")
# y ~ Trt + Age + V4 + +f(Ind, model = "iid")
result1 = inla(formula_2, family = "poisson", data = Epil, control.predictor = list(compute = TRUE))
identical(result, result1)
#FALSE
formula_2
is wrong and I just want a way of doing something like
formula_2 <- as.formula(paste("y ~", paste(paste(test_vars, collapse = "+"), "+", mm)))
where the desired output would be:
"y ~ Trt + Age + V4 + f(Ind, model = 'iid') + f(rand,model = 'iid')"
#where I can feed it directly into the model call:
result1 = inla(formula_2, family = "poisson", data = Epil, control.predictor = list(compute = TRUE))
I'd prefer to not directly manually quote ("f(Ind, model = 'iid') + f(rand, model = 'iid')"
) the random-effects as this masks the readability of it. I think parse
or eval
might help?
Thanks
I think this will do what you want
as.formula(paste0("y ~ ", paste(paste(test_vars, collapse="+"), deparse(mm), sep="+")))
# y ~ Trt + Age + V4 + f(Ind, model = "iid") + f(rand, model = "iid")
Since you are building the formula as a string, we really need everything as a string rather than a quoted expression. So deparse
will help turn that quoted expression into a string for easier manipulation.
Rather than storing mm
as a single quoted expression, it might be easier if you stored the additional terms you want as an expression collection. For example this would return the same thing
mm <- expression(
f(Ind, model = 'iid'),
f(rand, model = "iid")
)
reformulate(c(test_vars, sapply(mm, deparse)), "y")