拿到差异基因不知道做什么 基因富集分析教你从海量数据中锁定关键功能通路 附完整R代码教程
嗨,我懂你的迷茫。
刚刚跑完差异表达分析,甩给你几百上千个DEGs(差异表达基因),你盯着这份名单发呆——”这些基因是干嘛的?有什么关系?我要怎么从这里面找到故事?”
别慌,今天我就手把手教你,怎么把这些”孤儿基因”变成有血有肉的功能通路,让你写论文、做汇报时信手拈来。
一、先搞懂:为什么差异基因需要”抱团”?
想象一下这个场景:
你在医院急诊室,病人送进来一堆症状——发烧、咳嗽、乏力、肌肉酸痛。你盯着这个清单,一个个看好像没什么头绪。但如果有人告诉你:”这是流感,所有症状都指向同一个病原体”,你是不是瞬间就清晰了?
差异基因就是那些”症状”。单个基因告诉你什么?顶多告诉你”这个基因上调了2倍”。但一群基因一起告诉你什么?告诉你”细胞在经历氧化应激”、”免疫系统被激活”、”某个信号通路在疯狂工作”。
基因富集分析的本质,就是给这些孤儿基因找组织。
常见的方法有几种,你今天主要学最常用的两种:
- GO富集分析(Gene Ontology):回答”这些基因参与什么生物过程?”
- KEGG通路富集分析:回答”这些基因在哪些代谢/信号通路里?”
二、GO富集分析:基因功能的”三驾马车”
GO(Gene Ontology)把基因功能分成三个维度,每个维度就像一个分类文件夹:
1. BP(Biological Process,生物过程)
这一类告诉你基因参与什么”大事情”。比如:
- 细胞凋亡(apoptosis)
- 免疫反应(immune response)
- 细胞增殖(cell proliferation)
- 炎症反应(inflammatory response)
2. MF(Molecular Function,分子功能)
这一类告诉你基因”能干啥活”。比如:
- 蛋白激酶活性(protein kinase activity)
- 转录因子活性(transcription factor activity)
- 受体结合(receptor binding)
- 酶催化活性(enzyme catalysis)
3. CC(Cellular Component,细胞组分)
这一类告诉你基因”住在哪”。比如:
- 细胞膜(cell membrane)
- 细胞核(nucleus)
- 线粒体(mitochondrion)
- 核糖体(ribosome)
三、KEGG通路:基因工作的”社交圈”
如果说GO是问”这些基因在干嘛”,KEGG就是问”这些基因在哪个圈子混”。
KEGG(Kyoto Encyclopedia of Genes and Genomes)把基因功能映射到已知通路上,比如:
- MAPK信号通路:细胞增殖、分化
- PI3K-AKT信号通路:细胞存活、代谢
- TNF信号通路:炎症反应
- p53信号通路:DNA损伤修复、凋亡
- NF-κB信号通路:免疫调控
你的差异基因如果富集在某个通路上,说明这个通路在你的实验条件下”被激活”或”被抑制”。
四、完整R代码教程:从差异基因到富集结果
好了,理论讲完,上干货。
假设你已经跑完差异表达分析,得到这份数据(我稍后告诉你怎么准备):
第一步:准备你的差异基因列表
关键文件结构:
你需要一个Excel或CSV文件,包含:
- 第一列:基因ID(Symbol或Entrez ID)
- 第二列:log2FC(对数倍变)
- 第三列:P.Value(P值)
- 第四列:adj.P.Value(校正后的P值,FDR)
# 读取你的差异基因结果
deg <- read.csv("diff_genes.csv", header = TRUE)
head(deg)
示例输出:
gene log2FC P.Value adj.P.Value
1 TP53 2.35 0.0001 0.0012
2 IL6 -1.87 0.0003 0.0025
3 TNF 1.92 0.0005 0.0038
4 MYC 3.12 0.0001 0.0010
5 AKT1 -2.05 0.0002 0.0020
第二步:安装和加载必要的包
# 第一次运行需要安装,之后注释掉安装行
if (!require("clusterProfiler")) install.packages("clusterProfiler")
if (!require("org.Hs.eg.db")) install.packages("org.Hs.eg.db")
if (!require("GO.db")) install.packages("GO.db")
if (!require("KEGGREST")) install.packages("KEGGREST")
if (!require("ggplot2")) install.packages("ggplot2")
# 加载包
library(clusterProfiler)
library(org.Hs.eg.db) # 如果是小鼠用 org.Mm.eg.db
library(GO.db)
library(KEGGREST)
library(ggplot2)
cat("所有包加载成功!\n")
为什么用这些包?
clusterProfiler:富集分析的核心引擎org.Hs.eg.db:人类基因注解数据库(小鼠/大鼠换对应包)GO.db:GO术语数据库KEGGREST:从KEGG官网拉通路数据
第三步:基因ID转换(关键!)
问题:clusterProfiler需要Entrez ID,但你的数据可能是Symbol。
# 方法1:如果你的数据是Gene Symbol
gene_list <- deg$gene # 假设第一列是基因Symbol
# 转换为Entrez ID
entrez_ids <- bitmap::mapIds(org.Hs.eg.db,
keys = gene_list,
column = "ENTREZID",
keytype = "SYMBOL",
multiVals = "first")
# 去掉NA
entrez_ids <- na.omit(entrez_ids)
cat("成功转换", length(entrez_ids), "个基因ID\n")
方法2:如果你的数据已经是Entrez ID
entrez_ids <- deg$entrez_id # 直接用它
entrez_ids <- na.omit(entrez_ids)
方法3:如果你有一堆没转换成功的Symbol
# 查看哪些转换失败了
failed <- setdiff(gene_list, names(entrez_ids))
cat("转换失败的Symbol:", failed, "\n")
# 手动补充(如果数量不多)
manual_mapping <- c("GENE1" = "1234", "GENE2" = "5678")
entrez_ids <- c(entrez_ids, manual_mapping)
第四步:GO富集分析(BP/MF/CC)
# 设置显著性阈值
pval_cutoff <- 0.05
qval_cutoff <- 0.05
# ========== BP:生物过程 ==========
go_bp <- enrichGO(gene = entrez_ids,
OrgDb = org.Hs.eg.db,
keyType = "ENTREZID",
ont = "BP", # 选"BP"、"MF"或"CC"
pvalueCutoff = pval_cutoff,
qvalueCutoff = qval_cutoff,
readable = TRUE) # 返回Symbol而非Entrez ID
# ========== MF:分子功能 ==========
go_mf <- enrichGO(gene = entrez_ids,
OrgDb = org.Hs.eg.db,
keyType = "ENTREZID",
ont = "MF",
pvalueCutoff = pval_cutoff,
qvalueCutoff = qval_cutoff,
readable = TRUE)
# ========== CC:细胞组分 ==========
go_cc <- enrichGO(gene = entrez_ids,
OrgDb = org.Hs.eg.db,
keyType = "ENTREZID",
ont = "CC",
pvalueCutoff = pval_cutoff,
qvalueCutoff = qval_cutoff,
readable = TRUE)
cat("GO富集分析完成!\n")
cat("BP富集到", nrow(go_bp), "个GO术语\n")
cat("MF富集到", nrow(go_mf), "个GO术语\n")
cat("CC富集到", nrow(go_cc), "个GO术语\n")
结果解读:
# 查看BP的前10个结果
head(go_bp, 10)
ID Description GeneCount pvalue p.adjust qvalue geneRatio genes
1 GO:0006915 apoptosis regulatory process 45 1.2e-15 2.5e-12 1.8e-12 45/500 TP53,BAX,CASP3,...
2 GO:0006954 inflammatory response 38 3.5e-12 4.2e-10 3.1e-10 38/500 IL6,TNF,IL1B,...
3 GO:0007165 signal transduction 67 8.9e-11 7.5e-09 5.6e-09 67/500 MAPK1,AKT1,RAF1,...
4 GO:0006260 DNA replication 23 1.5e-08 9.8e-07 7.3e-07 23/500 PCNA,MCM5,RRM2,...
5 GO:0007049 cell cycle 52 2.3e-07 1.2e-05 9.0e-06 52/500 CDK1,CDC20,BUB1,...
关键列解释:
ID:GO术语的唯一标识符Description:这个GO术语叫什么GeneCount:富集到这个术语的差异基因数pvalue:原始P值(越小说明富集越显著)p.adjust:校正后的P值(FDR,通常<0.05认为显著)qvalue:类似p.adjust,但算法不同geneRatio:富集基因数/该GO术语总基因数genes:具体哪些基因富集在这里
第五步:KEGG通路富集分析
# KEGG富集分析
kegg <- enrichKEGG(gene = entrez_ids,
organism = "hsa", # hsa=人, mmu=小鼠, rno=大鼠
pvalueCutoff = pval_cutoff,
qvalueCutoff = qval_cutoff,
readable = TRUE)
cat("KEGG富集分析完成!\n")
cat("富集到", nrow(kegg), "个KEGG通路\n")
# 查看结果
head(kegg, 10)
ID Description Count Ngene pvalue p.adjust qvalue geneRatio genes
1 hsa04110 Cell cycle 28 28 2.5e-12 3.2e-10 2.4e-10 28/198 CDK1,CDC20,BUB1,...
2 hsa04210 Apoptosis 22 22 5.8e-11 4.5e-09 3.4e-09 22/198 TP53,BAX,CASP3,...
3 hsa04010 MAPK signaling pathway 18 18 1.2e-08 8.5e-07 6.4e-07 18/198 MAPK1,RAF1,BRAF,...
4 hsa04151 PI3K-AKT signaling pathway 15 15 3.5e-07 1.8e-05 1.4e-05 15/198 AKT1,MTOR,PTEN,...
5 hsa04060 NF-kappa B signaling pathway 12 12 8.9e-06 3.2e-04 2.4e-04 12/198 NFKB1,TNF,IL6,...
关键列解释:
ID:KEGG通路ID(如hsa04110)Description:通路名称Count:富集到的差异基因数Ngene:该通路总基因数pvalue:原始P值p.adjust:校正后P值genes:具体基因
第六步:可视化结果
1. 气泡图(Bubble Plot)
# GO BP气泡图
dotplot(go_bp, showCategory = 20) +
ggtitle("GO Biological Process Enrichment")
# KEGG气泡图
dotplot(kegg, showCategory = 20) +
ggtitle("KEGG Pathway Enrichment")
气泡图怎么看:
- X轴:GeneRatio(富集比例)
- Y轴:GO术语或KEGG通路名称
- 气泡大小:GeneCount(富集基因数,越大越重要)
- 气泡颜色:P值(越红越显著)
2. 柱状图(Bar Plot)
# GO BP柱状图
barplot(go_bp, showCategory = 15) +
ggtitle("Top 15 GO BP Terms")
# KEGG柱状图
barplot(kegg, showCategory = 15) +
ggtitle("Top 15 KEGG Pathways")
3. 网络图(Network Plot)
# GO网络图(展示术语之间的关系)
cnetplot(go_bp, categorySize = "pvalue", foldChange = deg$log2FC) +
ggtitle("GO BP Network")
# KEGG网络图
cnetplot(kegg, categorySize = "pvalue", foldChange = deg$log2FC) +
ggtitle("KEGG Pathway Network")
网络图怎么看:
- 每个节点代表一个GO术语或KEGG通路
- 节点颜色表示P值(越红越显著)
- 节点大小表示GeneCount
- 连线表示共享基因
4. 自定义美化图
# 更美观的KEGG柱状图
p <- barplot(kegg, showCategory = 20, drop = FALSE) +
theme_bw() +
theme(
axis.text.y = element_text(size = 10),
axis.text.x = element_text(angle = 45, hjust = 1),
plot.title = element_text(size = 14, face = "bold")
) +
ggtitle("Significant KEGG Pathways in Our Study")
print(p)
# 保存为高分辨率图片
ggsave("kegg_pathway.png", plot = p, width = 12, height = 8, dpi = 300)
第七步:提取关键基因和通路
# 提取显著富集的GO BP结果
go_result <- as.data.frame(go_bp)
significant_go <- go_result[go_result$p.adjust < 0.05, ]
# 查看最显著的5个通路
top5_go <- head(significant_go[order(significant_go$p.adjust), ], 5)
print(top5_go[, c("ID", "Description", "GeneCount", "p.adjust", "genes")])
ID Description GeneCount p.adjust
1 GO:0006915 apoptosis regulatory process 45 2.5e-12
2 GO:0006954 inflammatory response 38 4.2e-10
3 GO:0007165 signal transduction 67 7.5e-09
4 GO:0006260 DNA replication 23 9.8e-07
5 GO:0007049 cell cycle 52 1.2e-05
genes
1 TP53, BAX, CASP3, APAF1, CYCS, ...
2 IL6, TNF, IL1B, CXCL8, CCL2, ...
3 MAPK1, AKT1, RAF1, BRAF, SRC, ERK1/2, ...
4 PCNA, MCM5, RRM2, DNA2, ...
5 CDK1, CDC20, BUB1, AURKB, ...
接下来你可以:
- 把这5个通路的基因拿出来,做热图看看表达模式
- 在论文里写:”我们的差异基因显著富集在凋亡、炎症和细胞周期通路上(FDR < 0.05)”
- 画个通路图,标注哪些基因上调、哪些下调
第八步:用log2FC给基因染色(进阶)
# 准备fold change数据
fc_data <- deg[deg$gene %in% names(entrez_ids), ]
names(fc_data$log2FC) <- entrez_ids[match(fc_data$gene, gene_list)]
# 绘制KEGG通路图(带表达染色)
emapplot(kegg, foldChange = fc_data$log2FC) +
ggtitle("KEGG Pathways Colored by Expression")
这个图告诉你:
- 红色节点:通路中差异基因平均上调
- 蓝色节点:通路中差异基因平均下调
- 节点大小:通路显著性
五、结果解读:怎么写出论文级别的话?
示例段落(你可以直接参考):
为揭示差异表达基因的生物学功能,我们进行了GO和KEGG富集分析。结果显示,差异基因显著富集在以下生物过程:细胞凋亡调控(GO:0006915, FDR = 2.5e-12)、炎症反应(GO:0006954, FDR = 4.2e-10)和信号转导(GO:0007165, FDR = 7.5e-09)。KEGG通路分析进一步表明,差异基因主要富集在细胞周期(hsa04110)、凋亡通路(hsa04210)和MAPK信号通路(hsa04010)中(均FDR < 0.05)。这些结果提示,XX处理可能通过调控凋亡和炎症相关通路发挥生物学效应。
六、常见问题解答
Q1:我的基因转换失败了怎么办?
# 检查失败原因
failed_genes <- setdiff(gene_list, names(entrez_ids))
cat("失败基因数量:", length(failed_genes), "\n")
# 常见原因:
# 1. 基因名格式不对(试试用Entrez ID)
# 2. organism不对(小鼠用org.Mm.eg.db)
# 3. 基因名是旧版(用biomaRt包更新)
# 用biomaRt更新基因名
if (!require("biomaRt")) install.packages("biomaRt")
library(biomaRt)
mart <- useMart("ensembl", dataset = "hsapiens_gene_ensembl")
updated_genes <- getBM(attributes = c("external_gene_name", "entrezgene_id"),
filters = "external_gene_name",
values = failed_genes,
mart = mart)
Q2:富集结果太多怎么筛选?
# 方法1:只看FDR < 0.01的
top_go <- go_bp[go_bp$qvalue < 0.01, ]
# 方法2:只看GeneCount >= 10的
big_enrich <- go_bp[go_bp$geneCount >= 10, ]
# 方法3:只看最显著的10个
top10 <- head(go_bp, 10)
Q3:我的数据是小鼠/大鼠怎么办?
# 更换OrgDb包
library(org.Mm.eg.db) # 小鼠
# 或
library(org.Rn.eg.db) # 大鼠
# 更换KEGG organism参数
kegg <- enrichKEGG(gene = entrez_ids,
organism = "mmu", # 小鼠
pvalueCutoff = 0.05)
七、完整代码汇总(复制即用)
# ==================== 基因富集分析完整流程 ====================
# 1. 安装和加载包
if (!require("clusterProfiler")) install.packages("clusterProfiler")
if (!require("org.Hs.eg.db")) install.packages("org.Hs.eg.db")
library(clusterProfiler)
library(org.Hs.eg.db)
library(ggplot2)
# 2. 读取差异基因数据
deg <- read.csv("diff_genes.csv", header = TRUE)
# 3. 基因ID转换
entrez_ids <- bit::mapIds(org.Hs.eg.db,
keys = deg$gene,
column = "ENTREZID",
keytype = "SYMBOL",
multiVals = "first")
entrez_ids <- na.omit(entrez_ids)
# 4. GO富集分析(BP)
go_bp <- enrichGO(gene = entrez_ids,
OrgDb = org.Hs.eg.db,
keyType = "ENTREZID",
ont = "BP",
pvalueCutoff = 0.05,
qvalueCutoff = 0.05,
readable = TRUE)
# 5. KEGG富集分析
kegg <- enrichKEGG(gene = entrez_ids,
organism = "hsa",
pvalueCutoff = 0.05,
qvalueCutoff = 0.05,
readable = TRUE)
# 6. 可视化
dotplot(go_bp, showCategory = 20)
barplot(kegg, showCategory = 15)
cnetplot(go_bp, categorySize = "pvalue", foldChange = deg$log2FC)
# 7. 保存结果
write.csv(as.data.frame(go_bp), "GO_BP_result.csv", row.names = FALSE)
write.csv(as.data.frame(kegg), "KEGG_result.csv", row.names = FALSE)
cat("分析完成!结果已保存。\n")
八、下一步:让结果更有说服力
富集分析做完,你可以:
- 画热图:展示关键通路的基因表达模式
# 提取关键基因
key_genes <- unique(unlist(strsplit(as.character(go_bp$genes[1:5]), ", ")))
heatmap_data <- deg[deg$gene %in% key_genes, ]
# 画热图...
- 做GSEA:如果你不想设阈值,用GSEA看整体趋势
- 蛋白互作网络:用STRING数据库看基因之间的互作关系
好了,今天就到这里。你拿着这些代码,跑一遍自己的数据,应该能搞定90%的富集分析需求。
有问题随时问,咱们一起把这篇论文的故事讲清楚。
加油!🔬
