You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 10:52:42