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

如何修改R函数实现可选过滤的分组统计功能?

问题:修正R函数以支持可选过滤功能

拥有4个包含多个同名分类变量的大型数据框,编写了一个可指定分组变量、支持选择是否启用过滤功能的R函数,初始函数如下:

my_func <- function(grp.vars, filter.var = NULL, filter.par = NULL){
    
    filter.var <- enquo(filter.var)
    
    numerator <- DF1 %>% 
      filter(!!filter.var == filter.par) %>% 
      group_by(across({{grp.vars}})) %>% 
      summarise(numerator_var = n())
    
    den1 <- DF2 %>% 
      filter(!!filter.var == filter.par) %>% 
      group_by(across({{grp.vars}})) %>% 
      summarise(denominator_var_1 = n())
    
    den2 <- DF3 %>% 
      filter(!!filter.var == filter.par) %>% 
      group_by(across({{grp.vars}})) %>% 
      summarise(denominator_var_2 = n())
    
    den3 <- DF4 %>% 
      filter(!!filter.var == filter.par) %>% 
      group_by(across({{grp.vars}})) %>% 
      summarise(denominator_var_3 = n())
  
  suppressMessages( meta <- numerator %>% 
    left_join(den1) %>%
    left_join(den2) %>% 
    left_join(den3) %>% 
    mutate_if(is.numeric, list(~replace_na(., 0))) %>% 
    mutate(
      meta = round(100 * numerator_var / (denominator_var_1 + denominator_var_2 - denominator_var_3 ), 2)
    ) 
  )

  return(meta)

}

当指定filter.var和filter.par参数时函数可正常运行,但不传入过滤参数(即启用无过滤模式)时,抛出以下错误:

Error in `filter()`:
ℹ In argument: `NULL == filter.par`.
Caused by error:
! `..1` must be of size 1217618 or 1, not size 0.

需要修改函数使其支持选择是否进行过滤。


解决方案

核心思路是动态控制过滤逻辑:当未传入filter.var时,让filter()条件始终为TRUE(即保留所有行);当传入过滤参数时,执行指定的过滤操作。

修改后的函数如下:

my_func <- function(grp.vars, filter.var = NULL, filter.par = NULL){
    
    filter.var <- enquo(filter.var)
    # 构建动态过滤条件:有参数则过滤,无参数则返回所有行
    filter_condition <- if (!is.null(quo_get_expr(filter.var))) {
        expr(!!filter.var == filter.par)
    } else {
        expr(TRUE)
    }
    
    numerator <- DF1 %>% 
      filter(!!filter_condition) %>% 
      group_by(across({{grp.vars}})) %>% 
      summarise(numerator_var = n())
    
    den1 <- DF2 %>% 
      filter(!!filter_condition) %>% 
      group_by(across({{grp.vars}})) %>% 
      summarise(denominator_var_1 = n())
    
    den2 <- DF3 %>% 
      filter(!!filter_condition) %>% 
      group_by(across({{grp.vars}})) %>% 
      summarise(denominator_var_2 = n())
    
    den3 <- DF4 %>% 
      filter(!!filter_condition) %>% 
      group_by(across({{grp.vars}})) %>% 
      summarise(denominator_var_3 = n())
  
  suppressMessages( meta <- numerator %>% 
    left_join(den1) %>%
    left_join(den2) %>% 
    left_join(den3) %>% 
    mutate(across(where(is.numeric), ~replace_na(., 0))) %>% # 替换mutate_if为更推荐的across语法
    mutate(
      meta = round(100 * numerator_var / (denominator_var_1 + denominator_var_2 - denominator_var_3 ), 2)
    ) 
  )

  return(meta)

}

关键修改点:

  • 新增filter_condition变量,通过quo_get_expr()判断filter.var是否为有效表达式:
    • 若传入了filter.var,则生成!!filter.var == filter.par的过滤条件
    • 若未传入,则生成TRUE条件,让filter()保留所有行
  • 将原mutate_if(is.numeric, ...)替换为更现代的mutate(across(where(is.numeric), ...)),符合dplyr最新语法规范

使用示例:

  1. 启用过滤(按gender变量筛选值为"female"的行):
my_func(grp.vars = c(age_group, region), filter.var = gender, filter.par = "female")
  1. 不启用过滤(直接对全量数据分组统计):
my_func(grp.vars = c(age_group, region))

内容的提问来源于stack exchange,提问作者Rub

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 11:58:22