使用 tidyeval 在 map2 内部取消引用
Unquoting inside of map2 with tidyeval
我正在创建一个函数来计算 "runs" 或缺失或完整数据的数量 - 我希望它与 dplyr::group_by
一起使用,所以我将其编写为 S3 方法 - 下面是此代码的简化示例。
不幸的是,我发现裸露的未加引号的变量名不起作用,但引用它,这确实有效,这很奇怪。
下面是输出的例子
fun_run <- function(data, var) {
UseMethod("fun_run")
}
fun_run.default <- function(data, var) {
var <- rlang::enquo(var)
data_pull <- data %>% dplyr::pull(!(!var))
# find the lengths of the number of missings in a row
tibble::as_tibble(c(rle(is.na(data_pull))))
}
fun_run.grouped_df <- function(data, var) {
var <- rlang::enquo(var)
tidyr::nest(data) %>% dplyr::mutate(data = purrr::map2(.x = data, .y = !(!var),
.f = fun_run)) %>% tidyr::unnest()
}
library(dplyr)
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, union
airquality %>% fun_run(Ozone)
#> # A tibble: 35 x 2
#> lengths values
#> <int> <lgl>
#> 4 FALSE
#> 1 TRUE
#> 4 FALSE
#> 1 TRUE
#> 14 FALSE
#> 3 TRUE
#> 4 FALSE
#> 6 TRUE
#> 1 FALSE
#> 1 TRUE
#> ... with 25 more rows
# doesn't work
airquality %>% group_by(Month) %>% fun_run(Ozone)
#> Error in mutate_impl(.data, dots) : Evaluation error: object 'Ozone' not found.
# does work
airquality %>% group_by(Month) %>% fun_run("Ozone")
#> # A tibble: 37 x 3
#> Month lengths values
#> <int> <int> <lgl>
#> 5 4 FALSE
#> 5 1 TRUE
#> 5 4 FALSE
#> 5 1 TRUE
#> 5 14 FALSE
#> 5 3 TRUE
#> 5 4 FALSE
#> 6 6 TRUE
#> 6 1 FALSE
#> 6 1 TRUE
#> # ... with 27 more rows
你实际上并不想使用 map2
,因为你的第二个输入 (var
) 并没有随着第一个输入 (grouped/nested data
).此外,"Ozone" 列此时隐藏在嵌套数据中。您可以通过尝试在没有任何 tidyeval 语法的情况下执行代码来看到这一点:
data <- airquality %>% group_by(Month)
tidyr::nest(data) %>% dplyr::mutate(data = purrr::map2(.x = data, .y = Ozone,
.f = fun_run)) %>% tidyr::unnest()
#>Error in mutate_impl(.data, dots) :
#> Evaluation error: object 'Ozone' not found.
相反,您想使用标准 map
:
tidyr::nest(data) %>% dplyr::mutate(data = purrr::map(.x = data, var = Ozone,
.f = fun_run)) %>% tidyr::unnest()
重写后用于您的函数:
fun_run.grouped_df <- function(data, var) {
var <- rlang::enquo(var)
tidyr::nest(data) %>% dplyr::mutate(data = purrr::map(.x = data, var = !!var,
.f = fun_run)) %>% tidyr::unnest()
}
这会生成您最后引用的示例的结果。
我正在创建一个函数来计算 "runs" 或缺失或完整数据的数量 - 我希望它与 dplyr::group_by
一起使用,所以我将其编写为 S3 方法 - 下面是此代码的简化示例。
不幸的是,我发现裸露的未加引号的变量名不起作用,但引用它,这确实有效,这很奇怪。
下面是输出的例子
fun_run <- function(data, var) {
UseMethod("fun_run")
}
fun_run.default <- function(data, var) {
var <- rlang::enquo(var)
data_pull <- data %>% dplyr::pull(!(!var))
# find the lengths of the number of missings in a row
tibble::as_tibble(c(rle(is.na(data_pull))))
}
fun_run.grouped_df <- function(data, var) {
var <- rlang::enquo(var)
tidyr::nest(data) %>% dplyr::mutate(data = purrr::map2(.x = data, .y = !(!var),
.f = fun_run)) %>% tidyr::unnest()
}
library(dplyr)
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, union
airquality %>% fun_run(Ozone)
#> # A tibble: 35 x 2
#> lengths values
#> <int> <lgl>
#> 4 FALSE
#> 1 TRUE
#> 4 FALSE
#> 1 TRUE
#> 14 FALSE
#> 3 TRUE
#> 4 FALSE
#> 6 TRUE
#> 1 FALSE
#> 1 TRUE
#> ... with 25 more rows
# doesn't work
airquality %>% group_by(Month) %>% fun_run(Ozone)
#> Error in mutate_impl(.data, dots) : Evaluation error: object 'Ozone' not found.
# does work
airquality %>% group_by(Month) %>% fun_run("Ozone")
#> # A tibble: 37 x 3
#> Month lengths values
#> <int> <int> <lgl>
#> 5 4 FALSE
#> 5 1 TRUE
#> 5 4 FALSE
#> 5 1 TRUE
#> 5 14 FALSE
#> 5 3 TRUE
#> 5 4 FALSE
#> 6 6 TRUE
#> 6 1 FALSE
#> 6 1 TRUE
#> # ... with 27 more rows
你实际上并不想使用 map2
,因为你的第二个输入 (var
) 并没有随着第一个输入 (grouped/nested data
).此外,"Ozone" 列此时隐藏在嵌套数据中。您可以通过尝试在没有任何 tidyeval 语法的情况下执行代码来看到这一点:
data <- airquality %>% group_by(Month)
tidyr::nest(data) %>% dplyr::mutate(data = purrr::map2(.x = data, .y = Ozone,
.f = fun_run)) %>% tidyr::unnest()
#>Error in mutate_impl(.data, dots) :
#> Evaluation error: object 'Ozone' not found.
相反,您想使用标准 map
:
tidyr::nest(data) %>% dplyr::mutate(data = purrr::map(.x = data, var = Ozone,
.f = fun_run)) %>% tidyr::unnest()
重写后用于您的函数:
fun_run.grouped_df <- function(data, var) {
var <- rlang::enquo(var)
tidyr::nest(data) %>% dplyr::mutate(data = purrr::map(.x = data, var = !!var,
.f = fun_run)) %>% tidyr::unnest()
}
这会生成您最后引用的示例的结果。