如何根据metadata的Patient列合并dataframe样本并计算行均值
按Patient合并样本并计算基因表达均值
模拟数据加载
先还原你提供的模拟数据:
# 基因表达数据df1 df1 <- structure(list(Sample1 = c(102, 34, 77, 13, 10), Sample2 = c(1000, 23, 199, 0, 1), Sample3 = c(293, 234, 891, 230, 2002), Sample4 = c(672, 756, 431, 293, 0), Sample5 = c(28, 2910, 0, 120, 129)), class = "data.frame", row.names = c("GeneA", "GeneB", "GeneC", "GeneD", "GeneE")) # 元数据df2 df2 <- structure(list(Age = c(54, 70, 49, 23, 90), Patient = c(10, 10, 42, 108, 20)), class = "data.frame", row.names = c("Sample1", "Sample2", "Sample3", "Sample4", "Sample5"))
方法一:Base R 实现(无需额外包)
通过转置、分组聚合、再转置的方式完成需求:
# 转置df1,将样本转为行 df1_transposed <- t(df1) # 合并Patient信息 combined_data <- cbind(df1_transposed, Patient = df2$Patient) # 按Patient分组计算基因表达均值 patient_means <- aggregate(. ~ Patient, data = combined_data, FUN = mean) # 调整结构,恢复基因作为行名 result_base <- t(patient_means[, -1]) rownames(result_base) <- rownames(df1) colnames(result_base) <- paste0("Patient_", patient_means$Patient) # 输出结果 result_base
方法二:tidyverse 实现(代码更简洁)
借助dplyr和tidyr的管道语法,可读性更强,适合处理大型数据集:
library(tidyverse) result_tidy <- df1 %>% # 将基因名转为列,方便后续处理 rownames_to_column("Gene") %>% # 转为长格式数据 pivot_longer(cols = -Gene, names_to = "Sample", values_to = "Expression") %>% # 合并元数据中的Patient信息 left_join(df2 %>% rownames_to_column("Sample"), by = "Sample") %>% # 按基因和Patient分组,计算均值 group_by(Gene, Patient) %>% summarise(Mean_Expression = mean(Expression), .groups = "drop") %>% # 转回宽格式,恢复基因作为行名 pivot_wider(names_from = Patient, values_from = Mean_Expression, names_prefix = "Patient_") %>% column_to_rownames("Gene") # 输出结果 result_tidy
两种方法输出结果一致,最终得到的dataframe中,每一列对应一个Patient,每行是对应基因在该Patient所有样本中的表达均值。
内容的提问来源于stack exchange,提问作者Programming Noob
相关产品推荐
相关产品推荐

