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

如何在dplyr的summarise中复用自定义分组汇总函数

问题描述

我有一个数据框,需要应用自定义分组汇总逻辑:如果每组的最大值大于等于指定阈值,就用该组的最大值;否则用平均值。初始实现代码如下:

library(tidyverse)

dat <- data.frame(grp = c("a", "a", "a", "b", "b"),
           vals = c(115, 100, 101, 90, 100))

dat %>% 
  group_by(grp) %>% 
  summarise(new_val = case_when(max(vals) >= 100 ~ max(vals),
                                TRUE ~ mean(vals)))

但我想复用这个逻辑,并且能灵活更换阈值,不想重复硬编码。尝试了以下自定义函数但无法运行:

sumFunc <- function(max_val) {
  case_when(max(vals) >= max_val ~ max(vals),
            TRUE ~ mean(vals))
}

dat %>% 
  group_by(grp) %>% 
  summarise(new_val = sumFunc(100))

请问如何正确创建可复用的自定义函数?

解决方案

问题根源是自定义函数未明确接收数据列参数,无法在dplyr的分组上下文里识别vals列。以下是几种可行的实现方式:

方法1:基础自定义函数(单列处理)

让函数同时接收要计算的列和阈值参数,明确在函数内部处理列数据:

sumFunc <- function(col, max_val) {
  col_max <- max(col, na.rm = TRUE)
  if (col_max >= max_val) col_max else mean(col, na.rm = TRUE)
}

# 使用示例(阈值100)
dat %>% 
  group_by(grp) %>% 
  summarise(new_val = sumFunc(vals, 100))

# 更换阈值为95的示例
dat %>% 
  group_by(grp) %>% 
  summarise(new_val = sumFunc(vals, 95))

添加na.rm = TRUE是为了处理数据中可能存在的缺失值,提升函数鲁棒性。

方法2:适配across的函数(多列批量处理)

如果需要对多列应用该逻辑,可以编写嵌套函数配合across使用,方便批量操作:

sumFunc_across <- function(max_val) {
  function(col) {
    col_max <- max(col, na.rm = TRUE)
    col_max >= max_val ? col_max : mean(col, na.rm = TRUE)
  }
}

# 对vals列应用,阈值100
dat %>% 
  group_by(grp) %>% 
  summarise(across(vals, sumFunc_across(100), .names = "new_{col}"))

# 同时对多列应用(假设数据有vals1、vals2列)
# dat %>% 
#   group_by(grp) %>% 
#   summarise(across(c(vals1, vals2), sumFunc_across(100), .names = "new_{col}"))

方法3:支持字符串列名的函数(灵活指定列)

如果需要通过字符串传递列名,可以用rlang的准引用工具实现:

sumFunc_quo <- function(col_name, max_val) {
  col <- rlang::ensym(col_name)
  dat %>% 
    group_by(grp) %>% 
    summarise(new_val = case_when(
      max(!!col) >= max_val ~ max(!!col),
      TRUE ~ mean(!!col, na.rm = TRUE)
    ))
}

# 使用示例
sumFunc_quo("vals", 100)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 19:52:46