【问题标题】:How can I use function arguments where variables exist with the same name?如何在存在同名变量的情况下使用函数参数?
【发布时间】:2019-11-01 12:09:48
【问题描述】:

如果data.frame 中有一个列与我的函数的参数之一同名,则在尝试mutatefilter 时会使用该列名。

有没有办法显式使用函数参数?

可重现的例子:

my_function <- function(x) {
  my_tib <- tribble(
    ~x, ~y,
    1,  5,
    2,  10,
    3,  15
  )

  my_tib %>%
    mutate(z = x * y)
}

my_function(x=100)

## A tibble: 3 x 3
#      x     y     z
#  <dbl> <dbl> <dbl>
#1     1     5     5
#2     2    10    20
#3     3    15    45

想要的结果:

my_function(x=100)

## A tibble: 3 x 3
#      x     y     z
#  <dbl> <dbl> <dbl>
#1     1     5    500
#2     2    10    1000
#3     3    15    1500

【问题讨论】:

    标签: r dplyr tidyeval


    【解决方案1】:

    您可以使用{{ 运算符,尽管首先避免冲突似乎是避免可能出现的头痛的更好方法。

    library(dplyr)
    
    my_function <- function(x) {
      my_tib <- tribble(
        ~x, ~y,
        1,  5,
        2,  10,
        3,  15
      )
    
      my_tib %>%
        mutate(z = {{x}} * y)
    }
    
    my_function(100)
    
    # A tibble: 3 x 3
          x     y     z
      <dbl> <dbl> <dbl>
    1     1     5   500
    2     2    10  1000
    3     3    15  1500
    

    【讨论】:

    • 谢谢!出于某种原因,我不认为为此使用 NSE
    • 如果你不想使用 NSE,你可以强制 mutate() 使用环境变量 x 而不是数据变量 x!!。例如。 mutate(z = !!x * y)
    【解决方案2】:

    在目前接受的答案中,建议使用 curly-curly 代替函数参数。

    my_tib <- tribble(
      ~x, ~y,
      1,  5,
      2,  10,
      3,  15
    )
    
    my_function_nse <- function(data, x) {
      data %>% mutate(z = {{ x }} * y)
    }
    

    这适用于文字数字:

    my_tib %>% my_function_nse(100)
    #> # A tibble: 3 x 3
    #>       x     y     z
    #>   <dbl> <dbl> <dbl>
    #> 1     1     5   500
    #> 2     2    10  1000
    #> 3     3    15  1500
    

    但是,当您使用变量时,您会遇到相同的数据屏蔽问题:

    x <- 100
    my_tib %>% my_function_nse(x)
    #> # A tibble: 3 x 3
    #>       x     y     z
    #>   <dbl> <dbl> <dbl>
    #> 1     1     5     5
    #> 2     2    10    20
    #> 3     3    15    45
    

    这里发生的是数据变量x 优先于环境变量x。要解决此问题,用户需要使用强制运算符 !! 强制 env-var x

    my_tib %>% my_function_nse(!!x)
    #> # A tibble: 3 x 3
    #>       x     y     z
    #>   <dbl> <dbl> <dbl>
    #> 1     1     5   500
    #> 2     2    10  1000
    #> 3     3    15  1500
    

    你也可以在函数内部强制:

    my_function_se <- function(data, x) {
      data %>% mutate(z = !!x * y)
    }
    

    在这种情况下,您的函数根本不使用 NSE。不存在数据屏蔽问题:

    
    my_tib %>% my_function_se(x)
    #> # A tibble: 3 x 3
    #>       x     y     z
    #>   <dbl> <dbl> <dbl>
    #> 1     1     5   500
    #> 2     2    10  1000
    #> 3     3    15  1500
    

    当然,另一方面是您根本无法引用数据变量:

    my_tib %>% my_function_se(y + 10)
    #> Error : object 'y' not found
    
    my_tib %>% my_function_nse(y + 10)
    #> # A tibble: 3 x 3
    #>       x     y     z
    #>   <dbl> <dbl> <dbl>
    #> 1     1     5    75
    #> 2     2    10   200
    #> 3     3    15   375
    

    【讨论】:

    • 谢谢,我也没有意识到!! 会计算变量x。我想这取决于我想如何将参数输入到我的函数中,我应该使用!!x 还是!!enquo(x)(或更新的{{x}})。
    • 没错,这是一个 UI 选择。
    猜你喜欢
    • 2019-06-15
    • 1970-01-01
    • 2018-06-23
    • 2017-01-28
    • 1970-01-01
    • 1970-01-01
    • 2022-01-15
    • 2020-11-19
    • 1970-01-01
    相关资源
    最近更新 更多