I want to use env_get
to evaluate a variable in the grandparent environment (I think) of the mutate call, but I couldn't manage. I'm describing a minimal example below.
Given a list like the following:
library(dplyr)
l <- list(X = 10,
df = tibble(n = seq(-10,10), y = rnorm(21), z = runif(21)))
And custom mutate for these lists.
mutate_.list <- function(.data, ...){
mutate_(.data$df, ...)
}
I want a function that can be run inside the mutate and can use the value of X
. Something like the following which doesn't work:
addX <- function(x) {
X <- rlang::env_get(env = parent.frame(2), 'X', inherit = TRUE)
x + X
}
This works as expected.
mutate(l, n + 1)
And I would like to be able to do this:
mutate(l, addX(n))
And this doesn't work. I guess I should go up parents somehow and be able to refer to the list, but I couldn't manage. I tried to get the plausible names of the list arguments like this:
addX_test <- function(x) {
print(rlang::env_names(parent.frame(1)))
x
}
mutate(l, addX_test(n))
But I get stuff like the following:
[1] "~" ".top_env"
[3] ".__tidyeval_data_mask__." ".env"
Any pointers? Is it even doable?
Your X
is a field inside l
, so it's not directly visible in the corresponding environment. If you search for l
instead, you can then access its fields.
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
# ...
In general, it's not advisable to traverse the calling stack like that, because it breaks modularity of your code and introduces non-trivial dependencies that could lead to obscure bugs. In my opinion, a better approach is to use a function generator (function that returns a function), which will effectively bind the value of X
to the computation that uses it:
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
Note that this version is more robust to a name change for your list, because it no longer searches for l
directly.
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.