我有一个存储在变量中的调用。如果相关的话,该调用源自一个片面的公式:
f <- ~ a + b
rhs <- rlang::f_rhs(f)
rhs
#> a + b
由reprex package于2020年3月19日创建(v0.3.0)
现在,公式可能包含 bquote
式转义 .()
,我想获取所有转义名称。
查看bquote
的源代码,我创建了这个函数:
escapedNames <- function (expr, where = parent.frame())
{
unquote <- function(e) {
if (is.pairlist(e)) {
NULL
} else if (length(e) <= 1L) {
NULL
} else if (e[[1L]] == as.name(".")) {
deparse(e[[2L]])
} else {
x <- sapply(e, unquote)
unlist(x)
}
}
unquote(substitute(expr))
}
escapedNames(a + .(b) + c)
#> [1] "b"
正如您所看到的,它对于硬编码表达式来说效果很好。但是,我不知道如何传递存储在变量中的调用。
f <- ~ a + .(b)
rhs <- rlang::f_rhs(f)
escapedNames(rhs)
#> NULL
当然,这是完全有道理的,因为escapedNames
将它给出的任何内容视为我想要分析的调用,所以它不知道在之前扩展rhs
寻找名字。
那么,我该如何解决这个问题呢?
最佳答案
在发布赏金后,我立即想到了一种方法,但请告诉我更好的方法!
我们可以使用eval
和rlang::expr
在计算escapedNames
之前强制扩展公式变量:
escapedNames <- function (expr)
{
unquote <- function(e) {
if (is.pairlist(e) || length(e) <= 1L) NULL
else if (e[[1L]] == as.name(".")) deparse(e[[2L]])
else unlist(sapply(e, unquote))
}
unquote(substitute(expr))
}
formula <- ~ a + .(b) + c + .(d)
rhs <- rlang::f_rhs(formula)
eval(rlang::expr(escapedNames(!!rhs)))
#> [1] "b" "d"
由reprex package于2020年3月23日创建(v0.3.0)
关于r - 在传递给函数之前展开存储在变量中的调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60762048/