2026版RNA-seq入门实战(七):GO、KEGG富集分析与enrichplot超全可视化攻略

本节概览:
1.获取DEG结果的上下调差异基因
2.bitr()函数转化基因名为entrez ID
3.利用clusterProfiler进行KEGG与GO富集
4.用enrichplot进行富集结果可视化:pathview goplot barplot dotplot cnetplot emapplot treeplot heatplot upsetplot
ps:本次分析示例文件可在关注后私信领取~

承接上期文章:2026版RNA-seq入门实战(六):差异分析——DESeq2 edgeR limma的使用与比较 - 简书


1. 获取DEG结果的上下调差异基因

载入上节中保存的三种差异分析结果数据,这里示范选取DESeq2的结果数据,进行筛选条件设置后获取上下调基因名

# 环境准备
rm(list=ls())                      # 清空当前工作环境中的所有对象
options(stringsAsFactors = FALSE)  # 禁止字符串自动转换为因子

# 加载富集分析相关R包
library(clusterProfiler)   # 核心富集分析工具
library(enrichplot)        # 富集结果可视化
library(tidyverse)         # 数据处理与可视化套件
library(org.Mm.eg.db)      # 小鼠基因注释数据库(本示例为小鼠)
library(DOSE)              # 疾病本体语义富集分析
library(pathview)          # KEGG通路可视化

#数据载入与工作目录设置 
# setwd("目的文件夹")      # 根据实际项目路径设置工作目录(示例被注释掉)

# 加载基因表达计数矩阵
load(file = '1.counts.Rdata')

# 自动查找并加载指定文件夹下的差异分析结果文件(文件名包含"DEG_results.Rdata")
load(list.files(path = "./3.DEG", pattern = 'DEG_results.Rdata', full.names = TRUE))

# 创建富集分析输出文件夹,若已存在则跳过
dir.create("4.Enrichment_KEGG_GO")
setwd("4.Enrichment_KEGG_GO")  # 进入该文件夹,后续结果将保存在此

# 差异基因筛选阈值设置 
log2FC_cutoff <- log2(10)   # log2FoldChange阈值(对应原始差异倍数10倍)
pvalue_cutoff  <- 0.05      # 原始p值阈值
padj_cutoff    <- 0.05      # 多重检验校正后的p值(padj)阈值

# 提取上调和下调的差异基因
# 选择DESeq2差异分析结果中的关键列:log2FoldChange、pvalue、padj
# 根据实际情况可替换为其他工具结果(如DEG_limma_voom[,c(1,4,5)] 或 DEG_edgeR[,c(1,4,5)])
need_DEG <- DEG_DEseq2[, c(2,5,6)] 
head(need_DEG)  # 预览前几行,检查数据格式

# 将列名统一为易于理解的名称
colnames(need_DEG) <- c('log2FoldChange', 'pvalue', 'padj')

# 筛选上调基因:log2FC > 阈值 且 p值 < 阈值 且 矫正p值 < 阈值
gene_up <- rownames(need_DEG[
  with(need_DEG, log2FoldChange > log2FC_cutoff & 
                  pvalue < pvalue_cutoff & 
                  padj < padj_cutoff),
])

# 筛选下调基因:log2FC < -阈值 且 p值 < 阈值 且 矫正p值 < 阈值
gene_down <- rownames(need_DEG[
  with(need_DEG, log2FoldChange < -log2FC_cutoff & 
                  pvalue < pvalue_cutoff & 
                  padj < padj_cutoff),
])

# 注:
# gene_up / gene_down 为基因ID向量,可用于后续GO/KEGG富集分析
# 此处阈值设置较为宽松(FC>10, padj<0.05),可根据生物学问题调整

2. 转化基因名为entrez ID

在执行差异基因富集分析之前,需先将基因标识符统一为 Entrez ID。
进行转换前,要加载对应的物种注释数据库(如 human 用 org.Hs.eg.db,mouse 用 org.Mm.eg.db),这些库整合了多个主流数据库的标识信息,包含 Entrez ID、Ensembl 等类型。可通过 keytypes(org.Mm.eg.db) 查看该库支持的全部可转换 ID 类型。
通常使用 clusterProfiler 包中的 bitr() 或 mapIds() 函数来完成标识转换,典型用法如下:

# 基因ID转换:SYMBOL → ENTREZID
# 使用clusterProfiler的bitr函数将基因名从SYMBOL转换为ENTREZID
# 根据物种选择合适的OrgDb包:
#   人类 -> org.Hs.eg.db
#   小鼠 -> org.Mm.eg.db
# keytypes(org.Hs.eg.db)  # 可查看该数据库支持的所有ID类型,如 ENTREZID, ENSEMBL, SYMBOL 等

# 上调基因ID转换
gene_up_entrez <- as.character(na.omit(
  bitr(gene_up,                          # 待转换的基因向量(SYMBOL格式)
       fromType = "SYMBOL",              # 输入ID类型
       toType   = "ENTREZID",            # 目标ID类型
       OrgDb    = "org.Mm.eg.db"         # 小鼠基因组注释数据库
  )[, 2]                                 # 提取转换后的ENTREZID列
))

# 下调基因ID转换(流程同上)
gene_down_entrez <- as.character(na.omit(
  bitr(gene_down,
       fromType = "SYMBOL",
       toType   = "ENTREZID",
       OrgDb    = "org.Mm.eg.db"
  )[, 2]
))

# 合并全部差异基因(上、下调)的ENTREZID,并去重
gene_diff_entrez <- unique(c(gene_up_entrez, gene_down_entrez))
# 注:gene_diff_entrez 将用于后续富集分析,包含所有显著差异基因(不论方向)


3. 利用clusterProfiler进行KEGG与GO富集

在拿到差异基因(上调和下调)的 Entrez ID 后,就可以借助 clusterProfiler 包中的 enrichKEGG() 和 enrichGO() 来进行功能富集。这里只以上调基因为例演示富集分析的具体步骤;在实际研究里,建议对上调、下调以及全体差异基因分别进行富集分析,以便全方位考察结果。在分析过程中,需要留意以下几点:

  • pvalueCutoff 和 qvalueCutoff 的默认值分别是 0.05 和 0.2,实际分析中可根据需求灵活调整,以控制显著性和多重检验矫正的严格程度。
  • 在使用 enrichGO() 时,必须通过 OrgDb 指定物种注释库(如小鼠用 "org.Mm.eg.db");设置 readable = TRUE 可自动将 Entrez ID 转换为基因 Symbol;ont 参数可选择 "BP"(生物过程)、"MF"(分子功能)、"CC"(细胞组分)或 "ALL"(全部三类),分别对感兴趣的本体类别进行富集。
  • enrichKEGG() 中需要用 organism 指定物种(小鼠为 "mmu"),它没有 readable 选项,因此后续需借助 DOSE 包的 setReadable() 将结果中的 Entrez ID 转换成更可读的基因 Symbol。
#### KEGG、GO富集 ####
# KEGG 通路富集分析(上调基因)
kegg_enrich_results <- enrichKEGG(
  gene          = gene_up_entrez,   # 输入ENTREZID格式的上调基因
  organism      = "mmu",            # 物种缩写:人类 "hsa",小鼠 "mmu"
  pvalueCutoff  = 0.05,             # p值阈值
  qvalueCutoff  = 0.05              # 多重检验校正后的q值阈值
)

# 将ENTREZID替换为基因Symbol,方便结果解读
kk_read <- DOSE::setReadable(
  kegg_enrich_results,              # 富集结果对象
  OrgDb   = "org.Mm.eg.db",         # 小鼠基因组注释数据库
  keyType = "ENTREZID"              # 指明当前基因ID类型为ENTREZID
)  # 结果中会在ENTREZID列基础上新增SYMBOL等可读信息

# 输出KEGG富集结果表格
write.csv(kk_read@result, 'KEGG_gene_up_enrichresults.csv')
# 保存原始结果对象,便于后续可视化
save(kegg_enrich_results, file = 'KEGG_gene_up_enrichresults.Rdata')

#GO 富集分析(上调基因)
go_enrich_results <- enrichGO(
  gene          = gene_up_entrez,   # 使用相同的上调基因
  OrgDb         = "org.Mm.eg.db",   # 小鼠数据库
  ont           = "ALL",            # GO本体类型:"BP"(生物过程),"MF"(分子功能),
                                    # "CC"(细胞组分),"ALL"(包含全部三类)
  pvalueCutoff  = 0.05,             # p值阈值
  qvalueCutoff  = 0.05,             # q值阈值
  readable      = TRUE              # 自动将ENTREZID转换为基因Symbol
)

# 输出GO富集结果表格(文件名中“BP”为示例,实际包含全部本体)
write.csv(go_enrich_results@result, 'GO_gene_up_BP_enrichresults.csv')
# 保存GO富集结果对象
save(go_enrich_results, file = 'GO_gene_up_enrichresults.Rdata')

4. 富集结果可视化:pathview goplot barplot dotplot cnetplot emapplot treeplot heatplot upsetplot

富集通路后就要进行可视化展示了,参见clusterprofiler说明书 Introduction | Biomedical Knowledge Mining using GOSemSim and clusterProfiler (yulab-smu.top),其中enrichplot包可以对富集结果进行超级丰富的可视化。
下面就来总结介绍一下clusterprofiler说明书介绍的各种富集结果可视化方法,其中4.1pathview 只针对KEGG, 4.2goplot只针对GO结果,其他可视化方法则对两者都通用

4.1 pathview ——KEGG通路可视化

将KEGG通路进行可视化一般有以下三种方法:
*使用函数 browseKEGG(enrich_results, select_pathway)进行网页查看相关通路,如

browseKEGG(kegg_enrich_results, 'mmu04310') #网页查看通路
  • 网页版的pathview https://pathview.uncc.edu/guest-home,可以上传数据进行在线可视化

  • pathview包:
    在使用 pathview() 时,要给出含 log2 倍变化信息的 gene.data、目标通路的 pathway.id 以及 species,函数据此生成一幅在通路上标注了基因上、下调方向的通路图。
    需要特别留意参数 kegg.native:当设为 TRUE 时,会生成一幅包含完整 KEGG 通路的 PNG 图片;若设为 FALSE,则仅输出一张仅展示输入基因信息的 PDF 文件。
    参数limit可以对图例color bar范围(即log2FC范围)进行调整。
    其他参数使用详见官方说明:pathview.pdf (bioconductor.org),再推荐一篇简要中文教程:可视化kegg通路-pathview包 | KeepNotes blog (bioinfo-scrounger.com)
    下面我们选取富集排名第3(富集结果是按pvalue由小到大排序的)进行示范。

# 构建含 log2FoldChange 信息的基因列表
# 从差异分析结果中提取 log2FoldChange 值
# DEG_DEseq2 为之前获得的 DESeq2 差异分析完整结果,第2列为 log2FoldChange
genelist <- as.numeric(DEG_DEseq2[, 2])          # 提取 log2FC 值作为数值向量
names(genelist) <- row.names(DEG_DEseq2)          # 用基因SYMBOL命名向量元素

# 基因列表ID转换:SYMBOL → ENTREZID 
genelist_entrez <- genelist                       # 保留原始 log2FC 值
# 使用 bitr 将基因名从 SYMBOL 转换为 ENTREZID,作为新向量的名称
names(genelist_entrez) <- bitr(
  names(genelist),                                # 输入基因SYMBOL
  fromType = "SYMBOL",                            # 输入ID类型
  toType   = "ENTREZID",                          # 目标ID类型
  OrgDb    = "org.Mm.eg.db"                       # 小鼠数据库
)[, 2]                                            # 提取 ENTREZID 列
# 移除转换失败(NA)的基因
genelist_entrez <- genelist_entrez[!is.na(names(genelist_entrez))]
# 此时 genelist_entrez 为一个命名数值向量,names 为 ENTREZID,值为 log2FC

# 查看并选择目标通路 
# 需要先运行上一步的 KEGG 富集分析,得到 kk_read 对象
kk_read@result$Description[1:10]                  # 查看前10条富集通路的描述
i <- 3                                            # 选择第3条通路作为演示
select_pathway <- kk_read@result$ID[i]            # 获取该通路的 KEGG ID(如 mmu04512)

#  使用 pathview 绘制 KEGG 通路图
# 方式一:输出完整 KEGG 通路图(png格式),基因表达变化以颜色标注在通路图上
pathview(
  gene.data     = genelist_entrez,                # 含 log2FC 的命名向量
  pathway.id    = select_pathway,                 # 目标通路ID
  species       = 'mmu',                          # 物种:小鼠 mmu,人类 hsa
  kegg.native   = TRUE,                           # TRUE:输出原生KEGG通路PNG图
  new.signature = FALSE,                          # PDF相关参数,此处无效
  limit         = list(gene = 2.5, cpd = 1)       # 设置颜色标尺范围,gene上限2.5,化合物上限1
)

# 方式二:输出基因列表的 PDF 文件(仅含差异基因在通路上位置,非完整通路)
pathview(
  gene.data     = genelist_entrez,
  pathway.id    = select_pathway,
  species       = 'mmu',
  kegg.native   = FALSE,                          # FALSE:输出基因/化合物的简化PDF展示
  new.signature = FALSE,                          # PDF中是否添加自定义签名/标注
  limit         = list(gene = 2.5, cpd = 1)
)

参数kegg.native = T,所得如下:


参数kegg.native = F,所得如下:


4.2 goplot—— GO富集结果的有向无环图 directed acyclic graph

注意当enrichGO()的ont为'ALL'时不能运行该图,会报错。以下 goplot展示的是enrichGO()的ont='BP'时的go_enrich_results

### goplot : Gene Ontology is organized as a directed acyclic graph.有向无环图
gop <- goplot(go_enrich_results, showCategory = 10)
ggsave(gop, filename = "goplot.pdf", width=10, height=10)

4.3 barplot与dotplot——最常用的可视化图形

barplot 与 dotplot 主要用于展示富集通路的校正 p 值(p.adj)、基因比率(GeneRatio)以及计数(count)等信息。
如果将 enrichGO 的 ont 设为 "ALL",还可以在这两类图中按不同本体(ONTOLOGY)将通路分面,使 BP、CC、MF 的结果分别罗列,便于对比。

#绘制 GO 富集分析条形图(barplot) 
### barplot
# 基础条形图:展示前10个最显著的GO条目,字体大小14
barp <- barplot(go_enrich_results, font.size=14, showCategory=10)+
  theme(plot.margin=unit(c(1,1,1,1),'lines'))  # 调整图形四周边距,防止文字被截断

# 如果enrichGO的ont为'ALL'(即同时包含BP、MF、CC三类本体),则使用分面展示
if (T) {  # 此处始终为TRUE,因为上游设定 ont="ALL",强制采用分面
  barp <- barplot(go_enrich_results, split= "ONTOLOGY", font.size =14)+
    facet_grid(ONTOLOGY~., scale="free")+      # 按ONTOLOGY纵向分面,每类本体x轴范围自适应
    theme(plot.margin=unit(c(1,1,1,1),'lines')) #调整图形四周留白大小
}
# 保存条形图为PDF,文件名“barplot.pdf”,尺寸宽10高15英寸
ggsave(barp,filename = paste0("barplot",'.pdf'), width=10, height=15)


# 绘制 GO 富集分析气泡图(dotplot) 
### dotplot 
# 基础气泡图:展示所有显著富集的GO条目,字体14,图例键尺寸10pt
dotp <- enrichplot::dotplot(go_enrich_results,font.size =14)+
  theme(legend.key.size = unit(10, "pt"),#调整图例大小,使其更精致
        plot.margin=unit(c(1,1,1,1),'lines'))#调整四周留白大小,避免标签拥挤

# 同样,若GO结果包含多个ONTOLOGY,则按ONTOLOGY分面展示
if (T) {
  dotp <- enrichplot::dotplot(go_enrich_results,font.size =8,split = 'ONTOLOGY')+  # 分面后字体可适当调小
    facet_grid(ONTOLOGY~., scale="free")+      # 纵向分面,x轴(GeneRatio等)范围独立
    theme(legend.key.size = unit(10, "pt"),    #调整图例大小
          plot.margin=unit(c(1,1,1,1),'lines'))#调整四周留白大小
}
# 保存气泡图为PDF,文件名“dotplot.pdf”,尺寸宽10高12英寸
ggsave(dotp,filename = paste0("dotplot",'.pdf'),width =10,height =12)

4.4 cnetplot——Gene-Concept Network

cnetplot展示了各通路下的基因网络。绘制cnetplot有两种展现方式, 更改参数circular 为 F(默认)或T可以分别得到散布状和圈状分布的cnetplot;cnetplot还可以输入含log2FC信息的genelist ,会将log2FC信息展现在图中

# 基因-概念网络图(cnetplot) 
# cnetplot 用于展示基因与富集GO条目(概念)之间的关联网络,结合 log2FoldChange 着色

#--- 构建含 log2FoldChange 信息的基因列表 ---
# 从 DESeq2 差异分析结果中提取 log2FoldChange,用于对网络图中基因节点着色
genelist <- as.numeric(DEG_DEseq2[, 2])        # 提取 log2FoldChange 数值
names(genelist) <- row.names(DEG_DEseq2)       # 用基因 SYMBOL 命名

#--- 绘制网络图:所有节点均显示标签 ---
cnetp1 <- cnetp1 <- cnetplot(                  # 重复赋值(通常多余,保留原样)
  go_enrich_results,                           # GO 富集分析结果对象
  showCategory = 6,                            # 展示前6个最显著的GO条目
  foldChange   = genelist,                     # 提供基因的差异倍数,用于基因节点着色
  node_label   = "all"                         # 所有节点(基因与GO条目)均显示标签
)

#--- 绘制环形布局网络图:仅基因节点显示标签 ---
cnetp2 <- cnetp2 <- cnetplot(
  go_enrich_results,
  showCategory = 6,
  foldChange   = genelist,
  node_label   = "gene",                       # 仅对基因节点显示标签,概念节点不标
  layout       = "circle"                      # 使用圆形布局
)

# 保存网络图到 PDF 文件
ggsave(cnetp1, filename = 'cnetplot.pdf',      # 默认布局的网络图
       width = 12, height = 10)
ggsave(cnetp2, filename = 'cnetplot_cir.pdf',  # 圆形布局的网络图
       width = 15, height = 10)

4.5 emapplot ——Enrichment Map

emapplot富集图将被富集的术语组织成一个边缘连接重叠基因集的网络,相互重叠的基因集往往会聚集在一起,因此有助于我们识别功能模块。
注意使用emapplot前还需要用pairwise_termsim()处理富集结果

#富集网络图(Enrichment Map)
# 计算GO条目的两两语义相似度(默认方法为“jaccard”),构建用于网络图的相似矩阵
pt <- pairwise_termsim(go_enrich_results)

# 绘制富集网络图,节点代表GO条目,边表示相似性
emapp <- emapplot(pt,
                  showCategory = 30,           # 显示前30个最显著的GO条目
                  node_label   = 'category')   # 节点标签显示类别名称(可选:'category', 'group', 'all', 'none')

# 保存富集网络图为PDF,尺寸10x10英寸
ggsave(emapp, filename = 'emapplot.pdf', width = 10, height = 10)

4.6 heatplot: Heatmap-like functional classification

与cnetplot展示内容类似,但是将不同富集通路的相同基因聚在了一起,有助于我们更好识别基因模块

#  基因-功能热图(Heatplot) 
# heatplot 通过热图形式展示富集条目与相关基因的关联,并用颜色反映基因的差异表达水平

#--- 构建含 log2FoldChange 信息的基因列表(用于着色)---
genelist <- as.numeric(DEG_DEseq2[, 2])        # 提取 DESeq2 结果的 log2FoldChange 值
names(genelist) <- row.names(DEG_DEseq2)       # 用基因 SYMBOL 命名,确保与富集结果匹配

#--- 绘制热图 ---
heatp <- heatplot(go_enrich_results,           # GO 富集分析结果对象
                  foldChange = genelist,       # 提供基因变化倍数,用于热图颜色映射
                  showCategory = 5)            # 显示前5个最显著的GO条目

# 保存热图为 PDF,宽度加倍以适应基因名称等细节
ggsave(heatp, filename = 'heatplot.pdf', width = 20, height = 10)

4.7 upsetplot——不同富集通路间的重叠基因数量

upsetplot展示不同富集通路间的重叠基因数量。

# UpSet 图:展示不同基因集间的基因重叠 
# UpSet 图可直观显示多个基因集(此处为不同 GO 条目)所包含基因的交叉情况,
# 比传统韦恩图更适合展示大量集合间的重叠关系。

upsetp <- upsetplot(go_enrich_results, n = 10) +  # 对前10个最显著富集的GO条目绘制UpSet图
  theme(plot.margin = unit(c(1, 1, 1, 1), 'lines'))  # 调整图形四周边距,避免文字溢出

ggsave(upsetp, filename = 'upsetplot.pdf', width = 15, height = 10)  # 将UpSet图保存为PDF

4.7 treeplot——富集结果术语的层次聚类与高频词标记

treeplot 会对富集术语进行层次聚类,并用高频词加以标注,便于从繁杂的富集结果中迅速捕捉关键信息。
绘制 treeplot 之前,也要先用 pairwise_termsim() 对富集结果进行处理。

# 树图(Tree plot):展示GO条目间的层次聚类关系
# 再次计算GO条目间的成对语义相似度(与前文富集网络图类似)
pt <- pairwise_termsim(go_enrich_results)

# 基于语义相似度矩阵绘制树状图,直观呈现富集条目的聚类结构
treep <- treeplot(pt,
                  showCategory = 30)          # 显示前30个GO条目

# 保存树图为PDF,宽度18英寸以适应标签
ggsave(treep, filename = 'treeplot.pdf', width = 18, height = 10)

GO、KEGG富集与可视化到此就结束啦
如果所得显著差异基因很少,或无法富集到有生物学意义的通路时又该怎么办呢,下节将介绍一种不依赖于差异基因筛选的富集分析方法——GSEA

ps:本次分析示例文件可在关注后私信领取~
这里是两栖生物手册,中科院生物医学在读博士,正在努力成为贴心负责的RNA-seq分析者和实验技术分享者~

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容