如何将dplyr的group_by与filter批量操作封装为自定义函数
解决方案
核心通过purrr::reduce()实现迭代流程,搭配tidy非标准求值语法兼容任意变量传入需求,完整实现如下:
完整函数代码
library(tidyverse) # 你原有的辅助过滤函数 get_rows <- function(x) { u <- unique(x) n <- sample(c(if(is.character(x)) 0 else min(u)-1, u), 1) if(n == n[1]) TRUE else x == n } foo <- function(data, ..., exclude_vars = c("time"), group_var = "study", filter_fun = get_rows){ # 确定待处理变量列表:传入了变量就用传入的,否则自动取排除了exclude_vars和分组变量的所有列 if (length(list(...)) == 0) { process_vars <- setdiff(names(data), c(exclude_vars, group_var)) } else { process_vars <- names(dplyr::select(data, ...)) } # 迭代处理每个变量,等价于你手动分步执行的多步操作 res <- purrr::reduce( .x = process_vars, .f = function(current_df, var) { current_df %>% dplyr::group_by(!!sym(group_var)) %>% dplyr::filter(filter_fun(!!sym(var))) %>% dplyr::ungroup() }, .init = data ) return(res) }
使用示例
手动指定待处理变量
和你示例的三步操作完全等价:
data <- expand_grid(study=1:3,sample=1:2,group=1:3,outcome=c("A","B"),time=0:2) # 按顺序处理sample、group、outcome三个变量 result <- foo(data, sample, group, outcome)
自动处理符合规则的变量
不手动指定变量时,会自动排除exclude_vars指定的列和分组列,处理剩余所有列:
# 自动排除time,处理剩余的sample、group、outcome result_auto <- foo(data)
逻辑说明
reduce()会按顺序遍历待处理变量,每一轮都以上一轮处理完的数据框为输入,执行分组、过滤、解组操作,和你手动分步写的多段代码逻辑完全一致!!sym(var)用于将字符串格式的变量名转换为dplyr可识别的符号,适配非标准求值规则- 支持自定义分组变量、自定义过滤函数,可直接调整参数适配更多场景
内容的提问来源于stack exchange,提问作者Simon Harmel
相关产品推荐
相关产品推荐

