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

如何通过编程方式构建dplyr的summarize汇总语句?

dplyr动态生成summarise语句问题

我在进行dplyr编程时遇到问题:希望对任意数量的变量执行group_by操作(因此用到across),随后基于三组长度相同的向量:要应用函数的目标列、待应用的统计函数、生成的新列名称,编写summarize语句。
类似map或者apply语句的效果,我想最终执行的代码逻辑如下:

data %>%
  group_by(group_column) %>%
  summarize(new_name_1 = function_1(column_1),
            new_name_2 = function_2(column_2))

我知道如果使用across的话可以通过names参数调整列名,但我不确定across是不是最合适的实现方式。另外我后续要应用在规模较大的dataframe上,所以不希望额外计算不需要的列。

示例场景说明

期望输出结果

mtcars %>%
  group_by(across(c("cyl", "carb"))) %>%
  summarise(across(c("disp", "hp"), list(mean = mean, sd = sd))) %>%
  select(cyl, carb, disp_mean, hp_sd)
#> `summarise()` regrouping output by 'cyl' (override with `.groups` argument)
#> # A tibble: 9 x 4
#> # Groups:   cyl [3]
#>     cyl  carb disp_mean hp_sd
#>   <dbl> <dbl>     <dbl> <dbl>
#> 1     4     1      91.4 16.1 
#> 2     4     2     117.  24.9 
#> 3     6     1     242.   3.54
#> 4     6     4     164.   7.51
#> 5     6     6     145   NA   
#> 6     8     2     346.  14.4 
#> 7     8     3     276.   0   
#> 8     8     4     406.  21.7 
#> 9     8     8     301   NA

目前实际输出结果

mtcars %>%
  group_by(across(c("cyl", "carb"))) %>%
  summarise(across(c("disp", "hp"), list(mean = mean, sd = sd)))
#> `summarise()` regrouping output by 'cyl' (override with `.groups` argument)
#> # A tibble: 9 x 6
#> # Groups:   cyl [3]
#>     cyl  carb disp_mean disp_sd hp_mean hp_sd
#>   <dbl> <dbl>     <dbl>   <dbl>   <dbl> <dbl>
#> 1     4     1      91.4   21.4     77.4 16.1 
#> 2     4     2     117.    27.1     87   24.9 
#> 3     6     1     242.    23.3    108.   3.54
#> 4     6     4     164.     4.39   116.   7.51
#> 5     6     6     145     NA      175   NA   
#> 6     8     2     346.    43.4    162.  14.4 
#> 7     8     3     276.     0      180    0   
#> 8     8     4     406.    57.8    234   21.7 
#> 9     8     8     301     NA      335   NA

核心疑问

如何实现符合要求的动态summarize语句,避免生成多余计算列?

解决方案

不要直接用across给所有目标列套用所有函数,这种方式必然会生成多余的计算列。你可以通过rlang包的动态表达式注入功能,实现三组向量的一一对应计算,完全不会产生多余运算,适配大规模数据集的性能要求。

实现步骤

  1. 先定义你需要的参数向量:
library(dplyr)
library(rlang)

# 分组列向量
group_cols <- c("cyl", "carb")
# 三个等长的对应向量:目标列、要应用的函数、生成的新列名
target_cols <- c("disp", "hp")
apply_funs <- list(mean, sd)
new_colnames <- c("disp_mean", "hp_sd")
  1. 构造每个计算项的表达式:
sum_exprs <- purrr::map2(
  .x = target_cols,
  .y = apply_funs,
  ~ expr(!!sym(.x) %>% !!.y())
) %>% set_names(new_colnames)
  1. 把表达式注入到summarise中执行计算:
mtcars %>%
  group_by(across(all_of(group_cols))) %>%
  summarise(!!!sum_exprs, .groups = "drop_last")

运行上述代码得到的结果和你预期的输出完全一致,只会计算你指定的列组合,不会产生任何多余的中间计算结果,内存占用和运算效率都远高于先全量计算再筛选列的方案。如果不想依赖purrr,也可以用base R的mapply实现同样的表达式构造逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 13:27:01