在dplyr中如何用带引号变量名调用含省略号(...)的自定义函数?
dplyr中如何向省略号(...)传入字符型变量获取因子频数?
问题背景
我正在学习dplyr编程,尝试用省略号(...)编写自定义函数获取因子各水平的频数,相关代码及测试情况如下:
set.seed(10) data.frame(var1 = factor(sample(x = letters[1:3], size = 10, replace = T))) -> df levelFunct <- function(.data, ...) { .data %>% group_by(...) %>% summarise(count = n()) %>% mutate(tot = sum(count), perc = round(count/tot*100,2)) }
- 传入不带引号的变量名
var1调用levelFunct(df, var1)时,得到正确结果:
var1 count tot perc <fct> <int> <int> <dbl> 1 a 1 10 10 2 b 2 10 20 3 c 7 10 70
- 传入带引号的变量名
"var1"调用levelFunct(df, "var1")时,结果不符合预期(把字符串本身当成了分组依据):
`"var1"` count tot perc <chr> <int> <int> <dbl> 1 var1 10 10 100
请问如何使用带引号的变量名得到第一次调用的正确结果?
解决办法
要让函数同时兼容裸变量名和字符型变量名输入,只需对省略号参数做符号转换处理,推荐使用ensyms()配合解引用运算符!!!修改函数:
levelFunct <- function(.data, ...) { .data %>% group_by(!!!ensyms(...)) %>% summarise(count = n()) %>% mutate(tot = sum(count), perc = round(count/tot*100,2)) }
原理说明
ensyms(...)会将省略号中的每个参数(无论是裸变量名还是字符串格式的列名)转换为dplyr识别的符号对象,这是tidyverse中引用列名的标准格式。!!!(解引用运算符)会把转换后的符号对象集合展开,直接传递给group_by(),等价于直接传入裸变量名的效果。
验证结果
调用levelFunct(df, "var1"),得到正确输出:
var1 count tot perc <fct> <int> <int> <dbl> 1 a 1 10 10 2 b 2 10 20 3 c 7 10 70
这种方式还支持同时传入多个变量(混合裸变量名和字符型变量名),比如levelFunct(df, "var1", var2)也能正常分组统计。
内容的提问来源于stack exchange,提问作者llewmills
相关产品推荐
相关产品推荐

