简体   繁体   English

理解rlang:mutate with variable col name和variable column

[英]understanding rlang: mutate with variable col name and variable column

I'd like to define a function that takes a data.frame and a column name and returns the data.frame in with that column transformed (eg to lowercase). 我想定义一个带有data.frame和列名的函数,并返回data.frame,并将该列转换为(例如小写)。 When the column name is known in advance, this is simple: 当列名提前知道时,这很简单:

diamonds %>% mutate(cut = tolower(cut))

How do I define a function foo , such that: 如何定义函数foo ,例如:

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

does this same behavior? 做同样的行为吗? (Not looking for a base R or data.table answer since I want to preserve dplyr 's ability to translate this into a lazily-evaluated SQL call). (不寻找基本R或data.table答案,因为我想保留dplyr将其转换为懒惰评估的SQL调用的能力)。

If I just wanted my function to work using: foo(diamonds, cut) , I just need enquo and !! 如果我只是想让我的功能使用: foo(diamonds, cut) ,我只需要enquo!!

foo <- function(df, col){
    x <- enquo(col)
    mutate(df, !!x := tolower(!!x))
}

If I want to take the column name in quotes, foo(diamonds, "cut") , adding ensym is sufficient: 如果我想用引号中的列名, foo(diamonds, "cut") ,添加ensym就足够了:

foo <- function(df, col){
    col <- ensym(col)
    x <- enquo(col)
    mutate(df, !!x := tolower(!!x))
}

but this fails when given a variable for an argument: 但是当给出参数的变量时,这会失败:

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

Error in ~col : object 'col' not found

What am I missing that can evaluate the variable? 我错过了什么可以评估变量?

You can also avoid tidy eval entirely here by using mutate_at() . 您还可以使用mutate_at()完全避免整理eval。

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

Created on 2019-03-09 by the reprex package (v0.2.1.9000) reprex包创建于2019-03-09(v0.2.1.9000)

library(tidyverse)

col <- "cut"

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

foo(diamonds, col)

Check out Pass a string as variable name in dplyr::filter . 检查在dplyr :: filter中将字符串作为变量名传递

Going back to your original example, just use ensym() to convert text arguments to symbols, there is no need for a quosure in this case. 回到原始示例,只需使用ensym()将文本参数转换为符号,在这种情况下不需要quosure。

library(ggplot2)
col <- "cut"
foo <- function(df, col){
    col <- rlang::sym(col)
    dplyr::mutate(df, !!col := tolower(!!col))
}

foo(diamonds, col)
#> # A tibble: 53,940 x 10
#>    carat cut       color clarity depth table price     x     y     z
#>    <dbl> <chr>     <ord> <ord>   <dbl> <dbl> <int> <dbl> <dbl> <dbl>
#>  1 0.23  ideal     E     SI2      61.5    55   326  3.95  3.98  2.43
#>  2 0.21  premium   E     SI1      59.8    61   326  3.89  3.84  2.31
#>  3 0.23  good      E     VS1      56.9    65   327  4.05  4.07  2.31
#>  4 0.290 premium   I     VS2      62.4    58   334  4.2   4.23  2.63
#>  5 0.31  good      J     SI2      63.3    58   335  4.34  4.35  2.75
#>  6 0.24  very good J     VVS2     62.8    57   336  3.94  3.96  2.48
#>  7 0.24  very good I     VVS1     62.3    57   336  3.95  3.98  2.47
#>  8 0.26  very good H     SI1      61.9    55   337  4.07  4.11  2.53
#>  9 0.22  fair      E     VS2      65.1    61   337  3.87  3.78  2.49
#> 10 0.23  very good H     VS1      59.4    61   338  4     4.05  2.39
#> # … with 53,930 more rows

Created on 2019-03-11 by the reprex package (v0.2.1) reprex包创建于2019-03-11(v0.2.1)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM