如何按DataFrame唯一ID分组,计算所有数值列的80分位数?
解决方案
方法1:使用tidyverse工具(推荐)
先把宽格式数据转为长格式,让所有数值列合并到同一列,再按GeneID分组计算80分位数:
# 加载必要包 library(tidyverse) # 转换为长格式并计算分位数 result <- df %>% pivot_longer(cols = -GeneID, names_to = "variable", values_to = "value") %>% group_by(GeneID) %>% summarise(quantile_80 = quantile(value, probs = 0.8, na.rm = TRUE))
解释:
pivot_longer(cols = -GeneID)会把除GeneID外的所有列(第2至20列)转换为两列:variable记录原列名,value记录对应数值,让每个分组下的所有数值集中到同一列group_by(GeneID)按ID完成分组summarise中用quantile计算80分位数,na.rm = TRUE用于处理可能的缺失值,可根据你的数据情况调整
方法2:Base R实现(无需额外包)
如果不想依赖tidyverse,用base R工具也能完成:
方案A:转长格式后用aggregate计算
# 转长格式 long_df <- reshape(df, direction = "long", varying = names(df)[-1], v.names = "value", idvar = "GeneID", timevar = "variable") # 按GeneID分组计算80分位数 result <- aggregate(value ~ GeneID, data = long_df, FUN = function(x) quantile(x, probs = 0.8, na.rm = TRUE))
方案B:用by函数直接处理
# 按GeneID分组,提取数值列合并为向量后计算分位数 result <- do.call(rbind, by(df, df$GeneID, function(group) { # 提取第2到20列的所有数值,合并为单个向量 all_values <- unlist(group[, -1]) # 计算80分位数 quant_80 <- quantile(all_values, probs = 0.8, na.rm = TRUE) # 返回数据框格式的结果 data.frame(GeneID = unique(group$GeneID), quantile_80 = quant_80) }))
你之前的代码无法满足需求的原因
你之前的aggregate(GO~GeneID, data=df, FUN = function(x) paste0(x,collapse = '; '))仅针对单列(GO列)进行合并处理,每个分组只计算该列的分位数。而你的需求是把第2至20列的所有数值合并后计算分位数,因此必须先将多列数值整合为同一个向量,再执行分位数计算。
内容的提问来源于stack exchange,提问作者vp_050
相关产品推荐
相关产品推荐

