如何根据列名模式计算data.frame中每组三列的均值?
计算data.frame每三列分组均值的几种方法
针对你拥有的21列data.frame(第一列为geneName,剩余列每3个对应一个时间点组),这里提供几种R语言的实现方案:
先构造示例数据(方便测试)
df <- data.frame( geneName = c("gene1", "gene2"), t11 = c(3296, 4210), t12 = c(5133, 5505), t13 = c(3466, 4173), t21 = c(2166, 2736), t22 = c(1759, 2748), t23 = c(2099, 3052), t31 = c(1916, 2409), t32 = c(1379, 1944), t33 = c(1570, 2237), t41 = c(2533, 1158), t42 = c(1794, 3475), t43 = c(1016, 1488), t51 = c(800, 4023), t52 = c(79, 102), t53 = c(648, 940), t61 = c(99, 265), t62 = c(60, 365), t63 = c(152, 124) )
方法1:基础R实现
无需额外安装包,直接用原生函数处理:
# 提取数值列的列名 cols <- colnames(df)[-1] # 生成分组标识(去掉列名最后一位数字,得到t1/t2...t6) groups <- gsub("\\d$", "", cols) # 对每个分组计算行均值 mean_cols <- sapply(unique(groups), function(g) { rowMeans(df[cols[groups == g]]) }) # 合并geneName与均值结果,并重命名列 result <- cbind(df["geneName"], as.data.frame(mean_cols)) colnames(result)[-1] <- paste0("t", 1:6, "_mean")
方法2:tidyverse(dplyr+tidyr)实现
适合习惯tidy风格的用户,逻辑更直观:
library(dplyr) library(tidyr) result <- df %>% # 宽表转长表,统一处理分组 pivot_longer(-geneName, names_to = "time_group", values_to = "value") %>% # 提取时间组前缀 mutate(time_group = gsub("\\d$", "", time_group)) %>% # 分组计算均值 group_by(geneName, time_group) %>% summarise(mean_value = mean(value), .groups = "drop") %>% # 转回宽表格式 pivot_wider(names_from = time_group, values_from = mean_value, names_prefix = "mean_")
方法3:data.table实现
大数据量场景下效率更高:
library(data.table) dt <- as.data.table(df) # 生成分组标识 groups <- gsub("\\d$", "", colnames(dt)[-1]) # 计算各分组均值 mean_dt <- dt[, c( list(geneName = geneName), lapply(unique(groups), function(g) { rowMeans(.SD[, grep(g, colnames(.SD)), with = FALSE]) }) )] # 重命名列 colnames(mean_dt)[-1] <- paste0("t", 1:6, "_mean")
内容的提问来源于stack exchange,提问作者Assa Yeroslaviz
相关产品推荐
相关产品推荐

