我想使用env_get
来评估mutate调用的祖父母环境(我认为)中的变量,但是我无法管理。我在下面描述一个最小的例子。
给出如下列表:
library(dplyr)
l <- list(X = 10,
df = tibble(n = seq(-10,10), y = rnorm(21), z = runif(21)))
然后为这些列表自定义变量。
mutate_.list <- function(.data, ...){
mutate_(.data$df, ...)
}
我想要一个可以在mutate内部运行并可以使用的值的函数
X
。像下面这样的东西不起作用:
addX <- function(x) {
X <- rlang::env_get(env = parent.frame(2), 'X', inherit = TRUE)
x + X
}
这按预期工作。
mutate(l, n + 1)
我希望能够做到这一点:
mutate(l, addX(n))
这不起作用。我想我应该以某种方式上父母,并且能够 请参阅列表,但我无法管理。我试图这样获得列表参数的合理名称:
addX_test <- function(x) {
print(rlang::env_names(parent.frame(1)))
x
}
mutate(l, addX_test(n))
但是我得到如下信息:
[1] "~" ".top_env"
[3] ".__tidyeval_data_mask__." ".env"
有指针吗?甚至可行吗?
答案 0 :(得分:0)
您的X
是l
内的一个字段,因此在相应的环境中不直接可见。如果您搜索l
,则可以访问其字段。
addX( 1:3 ) # Error: object 'X' not found
addX_v2 <- function(x) {
ll <- rlang::env_get(env = parent.frame(2), 'l', inherit = TRUE)
x + ll$X
}
addX_v2( 1:3 )
# [1] 11 12 13
mutate( l, addX_v2(n) )
# # A tibble: 21 x 4
# n y z `addX_v2(n)`
# <int> <dbl> <dbl> <dbl>
# 1 -10 0.693 0.359 0
# 2 -9 -1.43 0.378 1
# 3 -8 -0.287 0.289 2
# 4 -7 -1.27 0.149 3
# ...
通常,不建议像这样遍历调用堆栈,因为它破坏了代码的模块化并引入了非平凡的依赖关系,这些依赖关系可能导致难以理解的错误。我认为,更好的方法是使用函数生成器(返回函数的函数),该函数可以将X
的值有效地绑定到使用它的计算中:
Xadder <- function( .list ) { function(x) {x + .list$X} }
addX_v3 <- Xadder( l )
addX_v3(1:3)
# [1] 11 12 13
mutate( l, addX_v3(n) ) # Works as expected
请注意,此版本对于列表的名称更改更可靠,因为它不再直接搜索l
。