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

如何高效实现多变量基于对应条件列的id1分组汇总统计?

问题描述

我需要对多个变量基于不同列条件做分组汇总统计。具体来说,有三个总差异变量:n.diff.total_rare、n.diff.total_general、n.diff.total_specialty,对应的还有三个用于排除观测的列(na.diff.total_*系列,值为1时排除该行对应变量的观测),需要按id1分组计算汇总统计。请问有没有比我当前写的重复代码更高效、更简洁的实现方式?

示例数据框

set.seed(100)
df <- 
  data.frame(
    id1 = c(rep('A', 10), rep('B', 10)),
    id2 = stri_rand_strings(20, 1),
    n.diff.total_rare = sample(0:30, 20, replace=TRUE),
    n.diff.total_general = sample(0:30, 20, replace=TRUE),
    n.diff.total_specialty = sample(0:30, 20, replace=TRUE),
    na.diff.total_rare = sample(0:1, 20, replace=TRUE),
    na.diff.total_general = sample(0:1, 20, replace=TRUE),
    na.diff.total_specialty = sample(0:1, 20, replace=TRUE)
  )

当前实现代码

output_rare <-
  df %>% 
  select(id1, id2, n.diff.total_rare, na.diff.total_rare) %>% 
  filter(na.diff.total_rare == 0) %>% 
  mutate(zero = ifelse(n.diff.total_rare == 0, 1, 0)) %>% 
  group_by(id1) %>% 
  summarise(
    min = min(n.diff.total_rare, na.rm = T),
    max = max(n.diff.total_rare, na.rm = T),
    sd = sd(n.diff.total_rare, na.rm = T),
    mean = mean(n.diff.total_rare, na.rm = T),
    zeros = sum(zero,  na.rm = T)
  ) %>% 
  ungroup %>% 
  mutate(variable = 'n.diff.total_rare')

output_specialty <-
  df %>% 
  select(id1, id2, n.diff.total_specialty, na.diff.total_specialty) %>% 
  filter(na.diff.total_specialty == 0) %>% 
  mutate(zero = ifelse(n.diff.total_specialty == 0, 1, 0)) %>% 
  group_by(id1) %>% 
  summarise(
    min = min(n.diff.total_specialty, na.rm = T),
    max = max(n.diff.total_specialty, na.rm = T),
    sd = sd(n.diff.total_specialty, na.rm = T),
    mean = mean(n.diff.total_specialty, na.rm = T),
    zeros = sum(zero,  na.rm = T)
  ) %>% 
  ungroup %>% 
  mutate(variable = 'n.diff.total_specialty')

output_general <-
  df %>% 
  select(id1, id2, n.diff.total_general, na.diff.total_general) %>% 
  filter(na.diff.total_general == 0) %>% 
  mutate(zero = ifelse(n.diff.total_general == 0, 1, 0)) %>% 
  group_by(id1) %>% 
  summarise(
    min = min(n.diff.total_general, na.rm = T),
    max = max(n.diff.total_general, na.rm = T),
    sd = sd(n.diff.total_general, na.rm = T),
    mean = mean(n.diff.total_general, na.rm = T),
    zeros = sum(zero,  na.rm = T)
  ) %>% 
  ungroup %>% 
  mutate(variable = 'n.diff.total_general')

output <- 
  output_rare %>% 
  rbind(
    output_specialty
  ) %>% 
  rbind(
    output_general
  )

优化实现方案

可以通过宽表转长表的方式消除重复代码,利用tidyr::pivot_longer将多列变量整合为行,只需要一次分组汇总逻辑即可完成所有变量的统计:

library(dplyr)
library(tidyr)

output_opt <- df %>%
  # 保留分组id,将差异变量和对应排除列转成长格式
  pivot_longer(
    cols = -c(id1, id2),
    names_to = c(".value", "variable"),
    names_pattern = "(n\\.diff\\.total|na\\.diff\\.total)_(.*)"
  ) %>%
  # 过滤需要保留的观测:排除标记为0的行
  filter(`na.diff.total` == 0) %>%
  # 计算是否为0的标记
  mutate(zero = as.integer(`n.diff.total` == 0)) %>%
  # 按分组id和变量名分组
  group_by(id1, variable) %>%
  summarise(
    min = min(`n.diff.total`, na.rm = TRUE),
    max = max(`n.diff.total`, na.rm = TRUE),
    sd = sd(`n.diff.total`, na.rm = TRUE),
    mean = mean(`n.diff.total`, na.rm = TRUE),
    zeros = sum(zero, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  # 调整变量名列的格式,和原输出保持一致
  mutate(variable = paste0("n.diff.total_", variable))

优化说明

  1. pivot_longer的关键作用:通过names_pattern正则匹配,将n.diff.total_xxx和na.diff.total_xxx对应起来,生成包含n.diff.total(变量值)、na.diff.total(排除标记)、variable(后缀:rare/general/specialty)的长表,避免重复处理每个变量。
  2. 逻辑复用:所有变量的过滤、计算零标记、分组汇总逻辑只需要写一次,代码更简洁且易维护——后续新增变量时,只需要保证列名符合现有命名规则,无需修改汇总逻辑。
  3. 性能更优:减少了重复的数据筛选和分组操作,尤其当数据量较大时,效率提升更明显。

内容的提问来源于stack exchange,提问作者J.K.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 21:12:07