我怎样才能重写使用整洁计算的函数(通过rlang的curly—curly)?

下面是一个基本的示例,我try 使用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

如何解决这个问题?

推荐答案

当您try 创建一个未加引号的符号向量c(cyl, vs, am, gear)时,R将try 在流水线的下一步之前对其进行判断.cylvsamgear都不存在于全球环境中,所以这将失败.

如果你想这样做,你可以明确告诉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))))

正如你所看到的,有很多方法可以采取—这被称为non-standard evaluation (NSE),这是一个广泛的主题.为了了解更多信息,我推荐阅读vignette("programming", package = "dplyr"){rlang} documentation中关于元编程的文章集.

R相关问答推荐

在R中使用自定义函数时如何删除该函数的一部分?

将带有范围的字符串转换为R中的数字载体

从API中抓取R数据SON

管道末端运行功能

在R中创建一个包含转换和转换之间的时间的列

通过使用str_detect对具有相似字符串的组进行分组

如果第一个列表中的元素等于第二个列表的元素,则替换为第三个列表的元素

如何计算多个日期是否在一个日期范围内

如何在所有绘图中保持条件值的 colored颜色 相同?

根据元素和前一个值之间的差值过滤矩阵的元素

在R中使用Scale_y_Break后更改y轴标签

展开对数比例绘图的轴(添加填充)

根据约束随机填充向量的元素

提高圣彼得堡模拟的速度

使用shiny 中的所选要素行下拉菜单

将工作目录子文件夹中的文件批量重命名为顺序

减少雨云面之间的间距并绘制所有统计数据点

整理ggmosaic图的标签

在REST API中使用参数R

如何在不使用SHINY的情况下将下拉滤镜列表添加到ggploy?