很多人第一次用 enrichGO(ont = "ALL") 画 barplot 时,会遇到一个小尴尬:你想看 BP/CC/MF 各自最显著的条目,但默认的 “TopN” 往往会被某一个本体占满,另外两个本体几乎看不到。
下面用两个很短的例子,把这个问题一次说清楚:
第一步用 split = "ONTOLOGY" 做到“每个本体各取 TopN”;第二步用 enrichplot::autofacet() 把 BP/CC/MF 自动分面排好。
准备数据:做一个 GO(ALL)富集结果
这里用 DOSE 自带的 geneList 凑一个演示用的基因集合,重点不在生物学含义,而在画图技巧。
library(DOSE)
data(geneList, package = "DOSE")
de <- names(geneList)[1:300]
library(clusterProfiler)
library(org.Hs.eg.db)
ego_all <- enrichGO(
gene = de,
OrgDb = org.Hs.eg.db,
keyType = "ENTREZID",
ont = "ALL",
readable = TRUE
)Example 1:不分面,但按本体分别取 TopN
关键点是这一句:split = "ONTOLOGY"。
它不是简单的“把条形图按本体上色”,而是会在内部做分组筛选:BP/CC/MF 各自选 showCategory 个条目,避免全局 TopN 把图“挤偏”。
library(enrichplot)
library(ggplot2)
p_nofacet <- barplot(
ego_all,
x = "Count",
showCategory = 15,
split = "ONTOLOGY"
) +
aes(fill = ONTOLOGY) +
scale_fill_brewer(palette = "Set2")
p_nofacet +
geom_text(aes(label = Count), nudge_x = 2) +
scale_y_discrete()
上面还顺手做了两件常见的小优化:
geom_text(aes(label = Count), nudge_x = 2):把 Count 直接标在条形旁边,读图更快。scale_y_discrete():用于覆盖barplot()默认的 y 轴标签格式化行为。
y轴的label,默认是被label_format = 30 是控制的,它主要做的是自动换行:超过一定长度就拆成多行;但其实你也可以传一个函数,想对label干啥的函数传进去是支持的。
如果你希望不换行、或者按你自己的方式控制 y 轴标签,你也可以直接加 + scale_y_discrete() 就能把默认处理覆盖掉。
Example 2:加上 autofacet,让 BP/CC/MF 自动分面
当 split = "ONTOLOGY" 生成的数据里包含 ONTOLOGY 这一列时,你可以直接加一行:
+ enrichplot::autofacet(by = "row", scales = "free")
它会按 ONTOLOGY 自动把图拆成三块面板(通常是 BP/CC/MF),并且因为 scales = "free",每个面板会按自己的条目数量和标签长度去排版,不会互相“拖累”。
p_facet <- barplot(
ego_all,
x = "Count",
showCategory = 15,
split = "ONTOLOGY"
) +
aes(fill = ONTOLOGY) +
scale_fill_brewer(palette = "Set2") +
enrichplot::autofacet(by = "row", scales = "free")
p_facet + scale_y_discrete()
小结:这套写法什么时候最有用?
如果你的 GO 富集结果来自 ont = "ALL",并且你希望:
- BP/CC/MF 各自展示一组 Top terms(而不是被全局 TopN “一锅端”)
- 一张图里看清三个本体,但又不想手动写
facet_grid()/facet_wrap() - 长标签如何显示(换行/不换行)想自己掌控
那就记住三件事:
split = "ONTOLOGY"负责“按本体分别取 TopN”;autofacet()负责“自动分面”;scale_y_discrete()负责“接管 y 轴标签的格式化”。