理解 rlang:使用变量 col 名称和变量列进行变异
understanding rlang: mutate with variable col name and variable column
我想定义一个函数,它接受一个 data.frame 和一个列名以及 returns 中的 data.frame 并转换该列(例如小写)。
当列名事先已知时,这很简单:
diamonds %>% mutate(cut = tolower(cut))
如何定义函数 foo
,使得:
col <- "cut"
foo(diamonds, col)
是否有同样的行为? (不寻找基本 R 或 data.table
答案,因为我想保留 dplyr
将其转换为延迟评估的 SQL 调用的能力)。
如果我只是想让我的函数使用:foo(diamonds, cut)
,我只需要 enquo
和 !!
foo <- function(df, col){
x <- enquo(col)
mutate(df, !!x := tolower(!!x))
}
如果我想在引号中使用列名,foo(diamonds, "cut")
,添加 ensym
就足够了:
foo <- function(df, col){
col <- ensym(col)
x <- enquo(col)
mutate(df, !!x := tolower(!!x))
}
但是当给参数一个变量时,这会失败:
col <- "cut"
foo(diamonds, col)
Error in ~col : object 'col' not found
我缺少什么可以评估变量?
library(tidyverse)
col <- "cut"
foo <- function(df, col) {
df %>%
mutate(!!sym(col) := tolower(!!sym(col)))
}
foo(diamonds, col)
查看 。
您也可以通过使用 mutate_at()
.
完全避免此处的 tidy 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
由 reprex package (v0.2.1.9000)
创建于 2019-03-09
回到你原来的例子,只使用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
由 reprex package (v0.2.1)
创建于 2019-03-11
我想定义一个函数,它接受一个 data.frame 和一个列名以及 returns 中的 data.frame 并转换该列(例如小写)。 当列名事先已知时,这很简单:
diamonds %>% mutate(cut = tolower(cut))
如何定义函数 foo
,使得:
col <- "cut"
foo(diamonds, col)
是否有同样的行为? (不寻找基本 R 或 data.table
答案,因为我想保留 dplyr
将其转换为延迟评估的 SQL 调用的能力)。
如果我只是想让我的函数使用:foo(diamonds, cut)
,我只需要 enquo
和 !!
foo <- function(df, col){
x <- enquo(col)
mutate(df, !!x := tolower(!!x))
}
如果我想在引号中使用列名,foo(diamonds, "cut")
,添加 ensym
就足够了:
foo <- function(df, col){
col <- ensym(col)
x <- enquo(col)
mutate(df, !!x := tolower(!!x))
}
但是当给参数一个变量时,这会失败:
col <- "cut"
foo(diamonds, col)
Error in ~col : object 'col' not found
我缺少什么可以评估变量?
library(tidyverse)
col <- "cut"
foo <- function(df, col) {
df %>%
mutate(!!sym(col) := tolower(!!sym(col)))
}
foo(diamonds, col)
查看
您也可以通过使用 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
由 reprex package (v0.2.1.9000)
创建于 2019-03-09回到你原来的例子,只使用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
由 reprex package (v0.2.1)
创建于 2019-03-11