在差异表达数据框中按组筛选Top5最值logFC基因的实现问题
问题解决:按组筛选差异表达基因的Top5和Bottom5
你的代码失效原因很明确:slice_max()和slice_min()是行筛选函数,用来直接提取符合条件的行,不能放在mutate()里生成列——mutate()的作用是给每行添加新的列值,两者用法场景完全不匹配。
下面提供两种符合需求的解决方案:
方案1:给所有基因标记是否为Top5/Bottom5
如果需要保留所有通过FDR筛选的基因,同时标记出每个组内logFC最大的5个和最小的5个,可以用排序函数生成标记列:
library(tidyverse) dex_df %>% filter(FDR < 0.05) %>% group_by(group) %>% # 给logFC降序排名,前5标记为Top5 mutate(is_top5 = dense_rank(desc(logFC)) <= 5, # 给logFC升序排名,前5标记为Bottom5 is_min5 = dense_rank(logFC) <= 5) %>% ungroup()
dense_rank()会处理并列值,比如多个基因logFC相同时,它们会获得相同排名,不会跳过位次;如果需要严格取前5个(不管并列),可以换成row_number()。
方案2:直接提取Top5和Bottom5的基因行
如果只需要每个组内的Top5和Bottom5基因数据集,可以直接用slice_max()/slice_min()提取后合并:
方法A:分步提取再合并
# 提取每个组的Top5基因 top5_genes <- dex_df %>% filter(FDR < 0.05) %>% group_by(group) %>% slice_max(logFC, n = 5, with_ties = FALSE) %>% mutate(category = "logFC_top5") %>% ungroup() # 提取每个组的Bottom5基因 min5_genes <- dex_df %>% filter(FDR < 0.05) %>% group_by(group) %>% slice_min(logFC, n = 5, with_ties = FALSE) %>% mutate(category = "logFC_min5") %>% ungroup() # 合并结果 final_result <- bind_rows(top5_genes, min5_genes)
方法B:用group_modify一次性处理
final_result <- dex_df %>% filter(FDR < 0.05) %>% group_by(group) %>% group_modify(~ bind_rows( slice_max(.x, logFC, n = 5, with_ties = FALSE) %>% mutate(category = "logFC_top5"), slice_min(.x, logFC, n = 5, with_ties = FALSE) %>% mutate(category = "logFC_min5") )) %>% ungroup()
- 参数
with_ties = FALSE表示当logFC有并列时,只取前5个(随机选择并列项);如果需要保留所有并列的基因,可以去掉这个参数。 - 如果某个组中通过FDR筛选的基因不足5个,函数会自动返回该组所有符合条件的基因,不会报错。
内容的提问来源于stack exchange,提问作者Sebastian Hesse
相关产品推荐
相关产品推荐

