简体   繁体   中英

Formula from list of quoted terms

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM