引用术语列表中的公式

Formula from list of quoted terms

假设我有一个引用术语列表:

l <- list(quote(x), quote(y), quote(I(z + 10)))

我想把它变成一个(单向的)公式:

~ x + y + I(z + 10)

最简单的方法是将所有内容都转换为文本并从头开始构建公式,即 deparse/reparse:

formula(paste("~", paste(l, collapse="+")))

这在幕后相当于

formula(paste("~", paste(sapply(l, deparse), collapse="+")))

但这似乎有点不雅,而且可能容易出现解析错误。有没有办法用纯语言操作得到公式?

可以通过逐项构建公式 RHS 以纯符号方式执行此操作。

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)

注意 out 看起来 像一个公式,但实际上是 class(和模式)call。要将其转换为实际公式,请使用 as.formula:

f <- as.formula(out)

但是,有时将输出保留为调用对象可能是有利的。特别是,如果项数非常大,创建公式可能会导致堆栈溢出:

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