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

R语言数据框中按列名后缀与time条件分组求均值的高效方法

高效批量计算分组列均值的通用解法

需求说明

当数据框中time==1时,对每组名称以...1S和...2S结尾的列(如ex1S、ex2S)求均值;当time==2时,对每组名称以...1C和...2C结尾的列(如ex1C、ex2C)求均值,最终生成以ave_为前缀的均值列。实际数据中存在多组此类列,需要无需手动逐个定义的通用解法。

当前低效解法

library(tidyverse)
Data %>%
  mutate(ave_ex = case_when(
    time == 1 ~ mean(c(ex1S, ex2S)),
    time == 2 ~ mean(c(ex1C, ex2C))
  ), 
  ave_id = case_when(
    time == 1 ~ mean(c(id1S, id2S)),
    time == 2 ~ mean(c(id1C, id2C))
  )) %>% select(-c(ex1S:id2C))

数据示例

Data = read.table(text = "
order DV    score  time  ex1S  ex2S  ex1C  ex2C  id1S  id2S  id1C  id2C     k     t
s-c   ac        1     1     8     5     6     1     2     4     3     7   400    30
s-c   bc        2     1     8     5     6     1     2     4     3     7   400    30
s-c   ac        3     2     8     5     6     1     2     4     3     7   600    50
s-c   bc        4     2     8     5     6     1     2     4     3     7   600    50
", header = TRUE)

期望输出

order time DV score   k   t ave_ex ave_id
s-c     1 ac     1 400  30    6.5      3
s-c     1 bc     2 400  30    6.5      3
s-c     2 ac     3 600  50    3.5      5
s-c     2 bc     4 600  50    3.5      5

通用解法一:基于长格式数据的批量处理

通过拆分列名提取前缀,按time筛选对应后缀的列,批量计算均值后再转回宽格式,自动适配任意多组目标列:

library(tidyverse)

compute_group_means <- function(df) {
  # 筛选所有符合*1S/*2S/*1C/*2C模式的列
  target_cols <- colnames(df)[str_detect(colnames(df), "\\d(S|C)$")]
  
  df %>%
    # 拆分列名为前缀(如ex、id)和后缀(如1S、2C)
    pivot_longer(cols = all_of(target_cols), 
                 names_to = c("prefix", "suffix"), 
                 names_pattern = "(.*)(\\d[S|C])$") %>%
    # 根据time匹配对应的后缀类型
    filter((time == 1 & str_ends(suffix, "S")) | (time == 2 & str_ends(suffix, "C"))) %>%
    # 按行标识和前缀分组计算均值
    group_by(across(-c(prefix, suffix, value)), prefix) %>%
    summarise(ave_value = mean(value), .groups = "drop") %>%
    # 转回宽格式并添加ave_前缀
    pivot_wider(names_from = prefix, values_from = ave_value, names_prefix = "ave_") %>%
    # 合并原数据的非目标列
    right_join(df %>% select(-all_of(target_cols)), by = intersect(colnames(.), colnames(df %>% select(-all_of(target_cols))))) %>%
    # 调整列顺序与期望输出一致
    select(order, time, DV, score, k, t, starts_with("ave_"))
}

# 运行函数得到结果
Desired_output <- compute_group_means(Data)
print(Desired_output)

通用解法二:基于across的动态列计算

利用dplyr的across函数动态匹配列名,无需转换长格式,代码更简洁:

library(tidyverse)

Data %>%
  rowwise() %>%
  mutate(
    # 自动提取所有目标列的前缀(如ex、id)
    across(
      unique(str_remove(colnames(.)[str_detect(colnames(.), "\\d(S|C)$")], "\\d(S|C)$")),
      # 根据time选择对应后缀的列计算均值
      ~ mean(c(
        pick(paste0(cur_column(), if_else(time == 1, "1S", "1C"))),
        pick(paste0(cur_column(), if_else(time == 1, "2S", "2C")))
      )),
      .names = "ave_{.col}"
    )
  ) %>%
  ungroup() %>%
  # 删除原有的*1S/*2S/*1C/*2C列
  select(-matches("\\d(S|C)$"))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 18:55:30