了解rlang:使用变量col名称和变量列进行变异

cbo*_*tig 2 r dplyr nse rlang

我想定义一个函数,该函数接受一个data.frame和一个列名,并以转换后的列(例如,转换为小写)的形式返回data.frame。如果事先知道列名,则很简单:

diamonds %>% mutate(cut = tolower(cut))
Run Code Online (Sandbox Code Playgroud)

我如何定义一个函数foo,例如:

col <- "cut"
foo(diamonds, col) 
Run Code Online (Sandbox Code Playgroud)

是否有同样的行为?(data.table因为我想保留dplyr的能力,而不是寻找基本的R或答案,所以我希望保留将其转换为延迟评估的SQL调用的能力)。

如果我只是想使用以下功能来工作:foo(diamonds, cut),我只需要enquo!!

foo <- function(df, col){
    x <- enquo(col)
    mutate(df, !!x := tolower(!!x))
}
Run Code Online (Sandbox Code Playgroud)

如果我想将列名用引号引起来 foo(diamonds, "cut"),则添加ensym就足够了:

foo <- function(df, col){
    col <- ensym(col)
    x <- enquo(col)
    mutate(df, !!x := tolower(!!x))
}
Run Code Online (Sandbox Code Playgroud)

但这在为变量提供变量时失败:

col <- "cut"
foo(diamonds, col) 

Error in ~col : object 'col' not found
Run Code Online (Sandbox Code Playgroud)

我缺少什么可以评估变量的信息?

jen*_*yan 7

您还可以使用来完全避免整洁的评估mutate_at()

library(tidyverse)

(x <- tibble(
  num = 1:3,
  month = month.abb[num]
))
#> # A tibble: 3 x 2
#>     num month
#>   <int> <chr>
#> 1     1 Jan  
#> 2     2 Feb  
#> 3     3 Mar

x %>%
  mutate(month = tolower(month))
#> # A tibble: 3 x 2
#>     num month
#>   <int> <chr>
#> 1     1 jan  
#> 2     2 feb  
#> 3     3 mar

foo <- function(df, col) {
  mutate_at(df, .vars = col, .funs = tolower)
}

foo(x, "month")
#> # A tibble: 3 x 2
#>     num month
#>   <int> <chr>
#> 1     1 jan  
#> 2     2 feb  
#> 3     3 mar

this <- "month"
foo(x, this)
#> # A tibble: 3 x 2
#>     num month
#>   <int> <chr>
#> 1     1 jan  
#> 2     2 feb  
#> 3     3 mar
Run Code Online (Sandbox Code Playgroud)

reprex软件包(v0.2.1.9000)创建于2019-03-09


djf*_*noy 5

library(tidyverse)

col <- "cut"

foo <- function(df, col) {
  df %>% 
    mutate(!!sym(col) := tolower(!!sym(col)))
}

foo(diamonds, col)
Run Code Online (Sandbox Code Playgroud)

查看在 dplyr::filter 中将字符串作为变量名传递