簡體   English   中英

使用rlang :: env_get在mutate調用的祖父母環境中評估變量

[英]Use rlang::env_get to evaluate a variable in the grandparent environment of the mutate call

我想使用env_get在mutate調用的祖父母環境(我認為)中評估變量,但是我無法管理。 我在下面描述一個最小的例子。

給出如下列表:

library(dplyr)

l <- list(X = 10,
        df = tibble(n = seq(-10,10), y = rnorm(21), z = runif(21)))

然后為這些列表自定義mutate。

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"

有指針嗎? 甚至可行嗎?

您的Xl內的字段,因此在相應的環境中不直接可見。 如果您搜索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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM