r - 如何使用整洁的评估为函数提供表达式 purrr::pmap
问题描述
我正在尝试编写一个函数,rlang
以便我可以根据提供的表达式对数据进行子集化。尽管实际功能很复杂,但这里有一个最小版本来说明问题。
所需功能的最小版本
library(rlang)
# define a function
foo <- function(data, expr = NULL) {
if (!quo_is_null(enquo(expr))) {
dplyr::filter(data, !!enexpr(expr))
} else {
data
}
}
# does the function work? yes
head(foo(mtcars, NULL)) # with NULL
#> mpg cyl disp hp drat wt qsec vs am gear carb
#> Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
#> Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
#> Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
#> Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
#> Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
#> Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
head(foo(mtcars, mpg > 20)) # with expression
#> mpg cyl disp hp drat wt qsec vs am gear carb
#> Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
#> Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4
#> Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1
#> Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1
#> Merc 240D 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2
#> Merc 230 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2
问题purrr::pmap
当与 一起使用时,它在ispurrr::pmap()
时按预期工作,但在其他情况下则不然。而不是,我还尝试使用来提供输入。expr
NULL
list
alist
library(purrr)
# works when expression is `NULL`
pmap(
.l = list(data = list(head(mtcars)), expr = list(NULL)),
.f = foo
)
#> [[1]]
#> mpg cyl disp hp drat wt qsec vs am gear carb
#> Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
#> Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
#> Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
#> Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
#> Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
#> Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
# but not otherwise
pmap(
.l = list(data = list(head(mtcars)), expr = list("mpg > 20")),
.f = foo
)
#> Error: Problem with `filter()` input `..1`.
#> ℹ Input `..1` is `"mpg > 20"`.
#> x Input `..1` must be a logical vector, not a character.
由reprex 包于 2021-07-20 创建 (v2.0.0 )
解决方案
完成这项工作的一种方法是用quote
purrr::pmap(
.l = list(data = list(head(mtcars)), expr = list(quote(mpg > 20))),
.f = foo
)
-输出
[[1]]
mpg cyl disp hp drat wt qsec vs am gear carb
Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
这也适用于NULL
pmap(
.l = list(data = list(head(mtcars)), expr = list(quote(NULL))),
.f = foo
)
[[1]]
mpg cyl disp hp drat wt qsec vs am gear carb
Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
相同的输出subset
subset(head(mtcars), mpg > 20)
mpg cyl disp hp drat wt qsec vs am gear carb
Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
或者另一种选择是通过更改来修改enexpr
功能parse_expr
foo1 <- function(data, expr = NULL) {
if (!quo_is_null(enquo(expr))) {
dplyr::filter(data, !!parse_expr(expr))
} else {
data
}
}
-测试
> pmap(
+ .l = list(data = list(head(mtcars)), expr = list(NULL)),
+ .f = foo1
+ )
[[1]]
mpg cyl disp hp drat wt qsec vs am gear carb
Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
>
> pmap(
+ .l = list(data = list(head(mtcars)), expr = list("mpg > 20")),
+ .f = foo1
+ )
[[1]]
mpg cyl disp hp drat wt qsec vs am gear carb
Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
推荐阅读
- mingw - 无法刷esp32
- python - python 2.7 - 登录尝试
- c++ - CMake 在多个目标上构建后自定义命令?
- javascript - ASP.NET MVC 如何防止 jquery 加载两次?
- java - 为什么在检查字符串是否可以是双精度时出现错误
- sql - How safe is this generated query from SQL injection?
- django - 在 dockerized 项目上运行 Django 迁移
- javascript - 在轮班名单上加快 fullcalendar.io
- java - 是否可以从参数中为列表命名?
- git - 当 rebase 失败而不是修改文件时,将差异输出到命令行