Say I have a list of quoted terms:
l <- list(quote(x), quote(y), quote(I(z + 10)))
and I want to turn this into a (one-sided) formula:
~ x + y + I(z + 10)
The simplest way to do this would be to turn everything into text and build the formula from scratch, ie, deparse/reparse:
formula(paste("~", paste(l, collapse="+")))
which, behind the scenes, is equivalent to
formula(paste("~", paste(sapply(l, deparse), collapse="+")))
But that seems a bit inelegant, and possibly prone to parsing screwups. Is there a way to obtain the formula with pure language manipulation?
It's possible to do this in a purely symbolic manner by building up the formula RHS term by term.
l <- list(quote(x), quote(y), quote(I(z + 10)))
out <- l[[1]]
for(i in seq_along(l)[-1])
{
out <- substitute(a + b, list(a=out, b=l[[i]]))
}
out <- call("~", out)
out
# ~x + y + I(z + 10)
Note that out
looks like a formula, but is actually of class (and mode) call
. To turn it into an actual formula, use as.formula
:
f <- as.formula(out)
However, it can sometimes be advantageous to leave the output as a call object. In particular, if the number of terms is very large, creating the formula can cause a stack overflow:
X <- paste0("x", 1:1e5)
X <- lapply(X, as.name)
out <- X[[1]]
for(i in seq_along(X)[-1])
{
out <- substitute(a + b, list(a=out, b=X[[i]]))
}
# this still works
out <- call("~", out)
f <- as.formula(out)
# Error: protect(): protection stack overflow
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.