解决R函数中mutate可选参数为NULL时的报错问题
问题描述
数据集
data <- data.frame(school_type = c("nursery", "nursery", "nursery", "nursery", "primary", "primary", "primary", "primary"), staff_type = c("manager", "manager", "teacher", "teacher", "manager", "manager", "teacher", "teacher"), age_group = c("20-30","30-40","20-30","30-40","20-30","30-40","20-30","30-40"), number_staff = c(40, 10, 20, 30, 40, 10, 20, 30))
对应的表格:
| school_type | staff_type | age_group | number_staff |
|---|---|---|---|
| nursery | manager | 20-30 | 40 |
| nursery | manager | 30-40 | 10 |
| nursery | teacher | 20-30 | 20 |
| nursery | teacher | 30-40 | 30 |
| primary | manager | 20-30 | 40 |
| primary | manager | 30-40 | 10 |
| primary | teacher | 20-30 | 20 |
| primary | teacher | 30-40 | 30 |
自定义函数
my_function <- function(group1 = NULL, group2 = NULL, nongroup = NULL){ data1 <- data %>% group_by({{group1}}, {{group2}} ) %>% summarise(number_staff = sum(number_staff, na.rm = T)) %>% mutate({{nongroup}} := "Total") return(data1) }
运行情况
- 示例1:传入
nongroup参数可正常运行
x <- my_function(group1 = school_type, group2 = staff_type, nongroup = age_group)
- 示例2:
nongroup设为NULL时报错,错误信息:
Error in
quos():
! The LHS of:=must be a string or a symbol
Runrlang::last_error()to see where the error occurred.
需求:让函数支持可选的nongroup参数,可根据场景选择是否添加额外列。
解决方案
核心思路是判断nongroup参数是否有效,仅当它不为空时执行添加列的操作,以下提供两种实现方式:
方法1:条件分支式实现
my_function <- function(group1 = NULL, group2 = NULL, nongroup = NULL){ data1 <- data %>% group_by({{group1}}, {{group2}} ) %>% summarise(number_staff = sum(number_staff, na.rm = T), .groups = "drop") # 仅当nongroup参数被传入时添加列 if (!is.null(enexpr(nongroup))) { data1 <- data1 %>% mutate({{nongroup}} := "Total") } return(data1) }
- 用
enexpr(nongroup)捕获参数表达式,避免直接判断NULL时的引用问题 - 添加
.groups = "drop"消除分组残留的警告
方法2:管道连贯式实现
my_function <- function(group1 = NULL, group2 = NULL, nongroup = NULL){ data %>% group_by({{group1}}, {{group2}} ) %>% summarise(number_staff = sum(number_staff, na.rm = T), .groups = "drop") %>% { # 条件判断决定是否执行mutate if (!is.null(enexpr(nongroup))) { mutate(., {{nongroup}} := "Total") } else { . } } }
这种方式用大括号包裹逻辑,保持管道的连贯性,无需额外变量赋值。
验证效果
- 不传
nongroup参数的输出:
my_function(group1 = school_type, group2 = staff_type)
| school_type | staff_type | number_staff |
|---|---|---|
| nursery | manager | 50 |
| nursery | teacher | 50 |
| primary | manager | 50 |
| primary | teacher | 50 |
- 传入
nongroup参数的输出:
my_function(group1 = school_type, group2 = staff_type, nongroup = age_group)
| school_type | staff_type | number_staff | age_group |
|---|---|---|---|
| nursery | manager | 50 | Total |
| nursery | teacher | 50 | Total |
| primary | manager | 50 | Total |
| primary | teacher | 50 | Total |
内容的提问来源于stack exchange,提问作者fe108
相关产品推荐
相关产品推荐

