资讯动态

转录组GO/KEGG富集分析全流程:从基因列表到通路图谱的实战指南

发布时间:2026/10/14 15:49:50 来源:尧图企业网站定制
1. 从表达矩阵到通路图谱KEGG与GO分析的整体设计思路做过转录组分析的人都有一个共识差异表达分析只是万里长征的第一步。拿到那一堆上调和下调的基因列表之后真正让人头疼的问题才刚刚开始——这些基因到底在干什么它们参与了哪些生物学过程集中在哪些信号通路上这时候GO和KEGG富集分析就成了绕不开的核心环节。我接触过的很多项目无论是肿瘤组织对比癌旁组织还是药物处理组对比对照组最终都要落到这两个数据库上。GO负责回答“这些基因的功能是什么”KEGG负责回答“这些基因参与了哪些通路”。两者配合使用基本能把一个基因列表的生物学意义勾勒出七八成。这篇内容就是把我自己在TCGA和GEO数据挖掘中反复使用的GO/KEGG分析流程完整梳理一遍从输入数据准备到最终出图每一步都讲清楚为什么这么做、怎么做、容易在哪里翻车。适合阅读这篇内容的人已经完成了差异表达分析、手里有基因列表想做功能富集的研究生刚接触生信分析、对clusterProfiler包还不熟悉的初学者以及做了很多次富集分析但结果总是不太理想、想排查问题的中级分析人员。我会尽量把每个参数的选择逻辑讲透让你不只是会跑代码而是知道每一步在干什么。整个分析流程的核心思路其实很朴素把基因列表映射到功能数据库上用统计检验找出显著富集的条目然后通过可视化手段呈现结果。但魔鬼藏在细节里基因ID的转换、背景基因集的选择、多重检验校正方法、富集结果的筛选阈值每一个环节都会直接影响最终结论的可靠性。2. 分析前的核心准备数据、工具与参数决策2.1 输入数据的三种常见形态与处理方式在实际项目里我拿到的输入数据通常有三种形式。第一种是差异表达分析后的基因列表包含基因名、logFC、p值、校正后p值等列这是最理想的情况。第二种是只有一列基因名没有统计量信息这种情况在GEO数据挖掘中特别常见比如从在线工具里导出的差异基因。第三种是表达矩阵加分组信息需要自己先做差异分析再进入富集流程。对于第一种情况我通常会用logFC的绝对值排序或者用校正后p值筛选。如果基因数量在500到3000之间直接拿全部差异基因做富集是合理的。如果差异基因超过5000个建议先用更严格的阈值筛一遍否则富集结果会过于宽泛失去聚焦性。对于第二种情况只有基因名列表时富集分析仍然可以做但后续没法做GSEA类的分析因为缺少排序依据。基因ID的转换是第一个容易出问题的环节。从TCGA或GEO拿到的数据基因标识可能是Ensembl ID、Entrez ID、Gene Symbol中的任意一种。clusterProfiler的enrichGO和enrichKEGG函数默认接受Entrez ID虽然新版本也支持其他类型但用Entrez ID最稳妥。我一般用org.Hs.eg.db包做转换代码大致是这样library(org.Hs.eg.db) gene_ids - bitr(gene_list, fromType SYMBOL, toType ENTREZID, OrgDb org.Hs.eg.db)这里有个坑要注意bitr转换会有丢失通常损失5%到15%的基因。如果丢失比例超过20%说明你的基因标识类型可能不是SYMBOL需要先确认原始数据的ID类型。另外如果做的是小鼠数据要把OrgDb换成org.Mm.eg.dbKEGG的organism参数也要相应调整。2.2 clusterProfiler的安装与版本选择clusterProfiler是Y叔团队开发的富集分析神器基本上是这个领域的标准工具。安装方式有两种CRAN版本和Bioconductor版本。我强烈建议用Bioconductor版本因为更新更及时而且依赖包的管理更规范。if (!requireNamespace(BiocManager, quietly TRUE)) install.packages(BiocManager) BiocManager::install(clusterProfiler) BiocManager::install(org.Hs.eg.db) BiocManager::install(enrichplot) BiocManager::install(ggplot2)版本方面clusterProfiler 4.x和3.x有一些函数参数的变化比如enrichKEGG的pvalueCutoff默认值、qvalueCutoff的处理逻辑等。如果你跟着旧教程跑代码报错大概率是版本不匹配。用packageVersion(clusterProfiler)查一下当前版本4.0以上的话基本可以用最新的写法。还有一个经常被忽略的包是DOSE它是clusterProfiler的底层依赖负责富集计算的核心逻辑。有时候clusterProfiler报错但提示信息指向DOSE这时候单独更新DOSE往往能解决问题。2.3 背景基因集的选择一个被低估的关键决策富集分析的统计检验本质上是比较“你的基因列表”和“背景基因集”中某个功能条目的比例差异。背景基因集选得对不对直接决定了结果的生物学意义。最常用的背景是“全基因组所有注释基因”也就是org.Hs.eg.db里所有有Entrez ID的人类基因大约两万个左右。这是clusterProfiler的默认行为适合大多数场景。但在某些情况下用全基因组做背景并不合适。比如你做的是RNA-seq数据但只有表达量大于某个阈值的基因才被纳入差异分析那么背景应该限定为“所有被检测到的基因”而不是全基因组。否则那些低表达、根本没机会被检测到的基因会稀释背景导致假阳性富集。我在处理TCGA数据时通常会把所有样本中表达量中位数大于1的基因作为背景基因集。这个阈值可以根据你的数据分布调整但核心原则是背景基因集应该代表“在你的实验条件下有机会被检测为差异表达的基因”。3. GO富集分析从代码到结果的完整拆解3.1 GO三个本体的独立分析与联合策略GO数据库分为三个本体BP生物学过程、CC细胞组分、MF分子功能。这三个本体回答的是完全不同维度的问题。BP描述的是基因参与的生物学过程比如“细胞周期调控”“免疫应答”CC描述的是基因产物在细胞中的定位比如“细胞核”“线粒体膜”MF描述的是基因产物的分子功能比如“ATP结合”“转录因子活性”。我见过很多人把三个本体混在一起做富集然后抱怨结果太杂。正确的做法是分别做富集分别出图。代码上只需要在enrichGO函数里指定ont参数ego_bp - enrichGO(gene gene_ids$ENTREZID, OrgDb org.Hs.eg.db, ont BP, pAdjustMethod BH, pvalueCutoff 0.05, qvalueCutoff 0.05, readable TRUE)ont参数可以取BP、CC、MF或ALL。取ALL会同时计算三个本体但后续可视化时需要分开处理。我个人的习惯是分别跑三次这样每个本体的结果可以独立调整筛选阈值和展示方式。readable参数设为TRUE会把Entrez ID转回Gene Symbol方便阅读。但这个转换在结果导出时有时会出问题如果后续要用其他工具做图建议先设为FALSE保留Entrez ID需要的时候再转。3.2 富集结果的筛选阈值p值、q值与p.adjust的取舍enrichGO的输出结果里最常看的列是pvalue、p.adjust和qvalue。这三个值容易让人混淆。pvalue是原始的超几何检验p值p.adjust是经过多重检验校正后的p值默认BH方法qvalue是另一种校正方式Storey方法。在clusterProfiler里pvalueCutoff和qvalueCutoff同时生效结果需要同时满足两个阈值才会被保留。我的经验是pvalueCutoff设0.05qvalueCutoff设0.2这样既能控制假阳性又不会漏掉太多有意义的条目。如果结果太少可以放宽到pvalueCutoff0.1但要在文章里说明。如果结果太多超过200条说明你的基因列表太宽泛或者阈值太松建议先收紧差异基因的筛选条件。还有一个细节p.adjust的计算是基于所有被检验的GO条目数量。人类GO数据库有将近两万个条目校正之后很多原本显著的条目会变得不显著。这是正常的也是必要的。如果你看到某个条目的pvalue是0.001但p.adjust是0.08不要觉得可惜这大概率是假阳性。3.3 GO富集结果的可视化条形图、气泡图与富集网络图可视化是GO分析的重头戏。clusterProfiler配合enrichplot包提供了多种图形我常用的有三种。条形图barplot最直观横轴是基因数量或显著性纵轴是GO条目名称。适合展示top 10到top 20的条目。代码很简单barplot(ego_bp, showCategory 15, title GO Biological Process)气泡图dotplot在条形图基础上增加了基因比例和p值的维度信息密度更高。横轴是GeneRatio点的大小是基因数量颜色是p.adjust。我一般用dotplot做主要展示图。dotplot(ego_bp, showCategory 20, split ONTOLOGY) facet_grid(ONTOLOGY~., scales free)富集网络图cnetplot适合展示基因和GO条目之间的对应关系能看出哪些基因是核心节点。但条目太多时图会很乱建议只展示top 5到top 8的条目。cnetplot(ego_bp, showCategory 5, foldChange gene_fc)这里有个实操心得出图之前一定要先看富集结果的表格确认条目名称是否合理。有时候会出现一些非常宽泛的条目比如“cellular process”“binding”这些条目虽然显著但生物学意义不大展示的时候可以考虑手动剔除。4. KEGG通路富集从ID转换到通路图渲染4.1 KEGG富集分析的特殊性与ID转换陷阱KEGG和GO最大的区别在于KEGG是一个有版权保护的数据库clusterProfiler通过KEGG的API在线获取数据。这意味着两件事第一分析时需要联网第二KEGG数据库会更新不同时间跑的结果可能有细微差异。enrichKEGG函数的基本用法ekegg - enrichKEGG(gene gene_ids$ENTREZID, organism hsa, pvalueCutoff 0.05, qvalueCutoff 0.2)organism参数用KEGG的三字母代码人类是hsa小鼠是mmu大鼠是rno。这个代码不能写错否则会报错或者返回空结果。KEGG富集最容易出问题的地方是ID转换。KEGG通路图里用的是KEGG自己的基因ID比如hsa:1234和Entrez ID有时候一致有时候不一致。enrichKEGG内部会做转换但转换率不是100%。如果你发现富集结果里某个通路的基因数量明显偏少可能是ID转换丢失导致的。另一个坑是KEGG的在线API偶尔会不稳定表现为函数运行很慢或者超时。我的应对方法是设置超时时间或者用KEGG.db包做离线分析。但KEGG.db已经停止更新了数据比较旧只适合做快速验证。4.2 KEGG结果的解读通路层级与基因定位KEGG通路是有层级结构的比如“Pathways in cancer”是一个顶层通路下面包含多个子通路。enrichKEGG默认返回的是最具体的通路层级但有时候你会看到一些很宽泛的通路名称比如“Metabolic pathways”这个通路包含上千个基因几乎任何基因列表都会富集到它。遇到这种情况我的处理方式是先看结果里有没有更具体的通路如果有优先解读具体的如果只有宽泛通路显著说明你的基因列表功能比较分散可能需要重新审视差异基因的筛选条件。KEGG结果的表格里有一列是geneID列出的是该通路中你的基因列表里的基因。这一列非常有用可以帮你快速定位关键基因。比如“PI3K-Akt signaling pathway”富集到了20个基因你可以看看这20个基因里有没有你特别关注的靶点。4.3 pathview通路图渲染把基因表达量画到通路上pathview是一个把基因表达数据映射到KEGG通路图上的包能生成非常直观的通路图。用法如下library(pathview) pathview(gene.data gene_fc, pathway.id hsa04151, species hsa, out.suffix PI3K_Akt)gene.data是一个命名向量名字是Entrez ID值是logFC。pathway.id是KEGG通路的编号比如hsa04151是PI3K-Akt通路。运行之后会在当前目录生成一个PNG文件通路图上的基因框会根据表达量着色红色代表上调绿色代表下调。pathview的坑在于第一它需要下载KEGG的XML文件网络不好的时候会失败第二基因框的着色有时候和你的数据对不上因为KEGG通路图里的基因ID和你的Entrez ID可能有差异第三通路图上的基因名是KEGG的缩写不是标准的Gene Symbol需要对照着看。我一般会把pathview生成的图作为补充材料主要结果还是用富集表格和气泡图展示。5. 常见问题与排查技巧实录5.1 富集结果为空或条目极少这是最常见的问题。可能的原因有四个基因ID类型不对、物种设置错误、阈值太严格、基因列表本身没有功能富集。排查步骤先用head(gene_ids)确认转换后的ID是数字Entrez ID再确认organism参数是否正确然后把pvalueCutoff放宽到0.1试试如果还是不行用enrichGO跑一下全基因组背景看看是不是你的基因列表确实没有显著富集。我遇到过一次基因列表里全是lncRNA做GO富集当然没有结果因为GO数据库主要注释的是蛋白编码基因。这种情况需要换用lncRNA专用的注释数据库。5.2 富集条目过多且宽泛如果富集结果超过300条而且很多是“cellular process”“binding”这类宽泛条目说明你的基因列表太大或者太杂。解决方案收紧差异基因的筛选阈值比如把p值从0.05降到0.01或者把logFC阈值从1提高到1.5。另外可以在富集结果里按p.adjust排序只看最显著的前50条。5.3 不同批次分析结果不一致同一个数据集今天跑和明天跑KEGG结果可能不一样。这是因为KEGG数据库在线更新。如果要做可重复的分析建议把KEGG结果保存下来后续分析直接读取保存的结果而不是重新跑。5.4 可视化图形中文乱码R语言在Windows下默认不支持中文GO条目名称里的中文会显示成方框。解决方案是在画图前设置字体library(showtext) showtext_auto()或者直接把GO条目名称转成英文反正GO的官方名称本来就是英文。5.5 富集分析的常见问题速查表问题现象可能原因排查方法解决方案结果为空ID类型错误检查ID是否为Entrez用bitr重新转换结果为空物种参数错误确认organism代码人类用hsa小鼠用mmu条目过多基因列表太大统计基因数量收紧差异基因阈值条目宽泛基因功能分散查看top条目聚焦具体通路结果不可重复KEGG在线更新对比两次结果保存结果文件图形中文乱码字体不支持查看图形输出设置showtext6. 从富集表格到生物学故事结果整合与输出6.1 多组学结果的联合展示策略如果你同时做了GO和KEGG而且有多个对比组比如不同分期、不同亚型怎么把结果整合起来展示是一个需要思考的问题。我常用的策略是用UpSet图展示不同对比组之间富集条目的交集用热图展示核心条目在不同组中的显著性变化。clusterProfiler的enrichplot包提供了upsetplot函数可以直接对多个富集结果做交集分析。热图的话需要先把多个富集结果整理成矩阵然后用pheatmap或ComplexHeatmap画图。6.2 富集结果的导出与报告生成富集结果最终要导出成表格方便后续写文章或做报告。我一般会导出三份文件完整的富集结果表格CSV格式、top 20条目的简化表格、以及所有图形的PDF版本。write.csv(as.data.frame(ego_bp), file GO_BP_results.csv, row.names FALSE) write.csv(as.data.frame(ekegg), file KEGG_results.csv, row.names FALSE)导出的时候注意编码问题Windows下用write.csv可能会中文乱码建议用write_excel_csv或者设置fileEncoding UTF-8。6.3 富集分析在文章中的呈现方式写文章的时候GO和KEGG结果通常放在结果部分的靠前位置作为功能探索的起点。我一般会放一张气泡图展示top 20条目再放一张pathview的通路图展示关键通路表格放在补充材料里。描述结果的时候不要只罗列条目名称要提炼出生物学主题。比如“富集结果显著集中在细胞周期调控和DNA损伤修复相关通路提示该基因集可能参与了基因组稳定性的维持”。这样的描述比单纯列条目要有价值得多。6.4 进阶方向GSEA与GSVA如果你手里有完整的表达矩阵和分组信息除了传统的过表达富集分析还可以做GSEA基因集富集分析和GSVA基因集变异分析。GSEA不需要预先筛选差异基因而是对所有基因按表达量排序后检验基因集的富集趋势能发现一些传统方法漏掉的微弱但协调的变化。GSVA则可以把基因集水平的表达变化量化成评分适合做样本间的比较。这两个方法在clusterProfiler和GSVA包里都有实现等把基础富集分析跑通之后可以作为下一步的扩展方向。6.5 我个人在富集分析中的几个习惯最后分享几个我做了几十次富集分析之后养成的习惯。第一每次分析前先保存一份原始基因列表和转换后的ID对照表方便回溯。第二富集结果一定要手动看一遍top条目不要只看图表格里往往藏着关键信息。第三不同批次的样本最好分开做富集再比较而不是混在一起做这样能发现批次特异的信号。第四KEGG结果里的通路编号要记下来写文章的时候需要引用。第五如果结果不理想先检查数据质量而不是反复调参数——大部分时候问题出在输入数据上而不是分析工具上。富集分析这个环节工具和代码其实不是门槛真正的门槛在于对结果的理解和解读。同样的富集结果有经验的人能从中提炼出生物学故事没经验的人只能看到一堆条目名称。希望这篇内容能帮你跨过这个门槛把GO和KEGG分析真正变成你研究中的有力工具。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑