使用整洁的评估(卷曲-卷曲)和 purrr

问题描述 投票:0回答:2

如何迭代使用整洁评估的函数(通过

rlang
的 curly-curly)?

这是一个基本示例,我尝试使用

purrr::map()
迭代列名称:

library("dplyr")
library("purrr")

myfunc <- function(by) {
  mtcars %>% count({{ by }})
}

# passing unquoted arguments doesn't work
c(cyl, vs, am, gear) %>% map(~ myfunc(by = .x))
#> Error in eval(expr, envir, enclos): object 'cyl' not found

# passing quoted arguments also doesn't work
c("cyl", "vs", "am", "gear") %>% map(~ myfunc(by = .x))
#> Error in `map()`:
#> ℹ In index: 1.
#> Caused by error in `count()`:
#> ! Must group by variables found in `.data`.
#> ✖ Column `.x` is not found.

创建于 2024-03-18,使用 reprex v2.1.0

如何解决这个问题?

r purrr rlang
2个回答
1
投票

当您尝试创建不带引号的符号向量

c(cyl, vs, am, gear)
时,R 将尝试在管道中的下一步之前对其进行评估。全局环境中不存在
cyl
vs
am
gear
,因此这将失败。

如果你想以这种方式做事,你可以明确告诉 R 这些参数直到稍后才被评估,这可以使用

rlang::quos()
:

来完成
library(dplyr)
library(purrr)

myfunc <- function(by) {
  mtcars %>% count({{ by }})
}

# passing unquoted arguments doesn't work
rlang::quos(cyl, vs, am, gear) %>% map(~ myfunc(by = !!.x))
#> [[1]]
#>   cyl  n
#> 1   4 11
#> 2   6  7
#> 3   8 14
#> 
#> [[2]]
#>   vs  n
#> 1  0 18
#> 2  1 14
#> 
#> [[3]]
#>   am  n
#> 1  0 19
#> 2  1 13
#> 
#> [[4]]
#>   gear  n
#> 1    3 15
#> 2    4 12
#> 3    5  5

创建于 2024-03-18,使用 reprex v2.1.0

请注意,您还需要使用

!!
才能正常工作 - 否则 R 将查找名为
.x
的列。

更惯用的方法是使用字符向量并对

.data
代词进行子集化,如下所示:

c("cyl", "vs", "am", "gear") %>% 
  map(~ myfunc(by = .data[[.x]]))

您还可以将

across()
all_of()
结合使用:

c("cyl", "vs", "am", "gear") %>% 
  map(~ myfunc(by = across(all_of(.x))))

如您所见,您可以采取多种方法 - 这是一个广泛的主题。要了解更多信息,我建议阅读

vignette("programming", package = "dplyr")


0
投票

这是解决此问题的一种替代方法:

c("cyl", "vs", "am", "gear") %>% map(~ myfunc(by = !!sym(.)))

[[1]]
  cyl  n
1   4 11
2   6  7
3   8 14

[[2]]
  vs  n
1  0 18
2  1 14

[[3]]
  am  n
1  0 19
2  1 13

[[4]]
  gear  n
1    3 15
2    4 12
3    5  5
© www.soinside.com 2019 - 2024. All rights reserved.