富集分析天花板之ClusterProfiler4

说在前面

在国内做生信的小伙伴或多或少都听过一个大名鼎鼎的名字---Y叔,想当初小编初入生信大门时还专门百度查了一下,他就是南方医科大学生物信息学系主任余光创教授。Y叔在国际也有很高的知名度,以至于ClusterProfiler 4在发出后有很多国际知名生信学家评论。

生物信息学软件很多都死在故纸堆里,发表文章之后,就走向毁灭,这叫publish and perish。clusterProfiler之所以能够成功,因为Y叔对它充满感情,10年如一日地维护,但是自2012年发表一篇文章以来,虽然软件一直在更新,但相应的文章一直没有再发一版。时隔9年,Y叔终于再出一篇文章,而且是把论文写在祖国大地上,clusterProfiler 4.0发表在中科院青促会主办的期刊The Innovation。下面附上文章信息:T Wu#, E Hu#, S Xu, M Chen, P Guo, Z Dai, T Feng, L Zhou, W Tang, L Zhan, X Fu, S Liu, X Bo, G Yu. clusterProfiler 4.0: A universal enrichment tool for interpreting omics data. The Innovation. 2021, 2(3):100141. doi: 10.1016/j.xinn.2021.100141。

截至目前,第一版的ClusterProfiler已经被引用了5000次,文章在G Yu, LG Wang, Y Han and QY He*. clusterProfiler: an R package for comparing biological themes among gene clusters. OMICS: A Journal of Integrative Biology. 2012, 16(5):284-287. doi: 10.1089/omi.2011.0118,国内很难再有一个单独R包可以达到这个高度。那么,新版的ClusterProfiler 4.0又给我们带来什么样的惊喜你额,今天小编就来简单介绍一下这个伟大R包的新版本。


GO富集分析

ClusterProfiler最经典、最重要的一个功能就是GO富集分析了,新版的GO分析有groupGO(),enricogo()和gseGO()三个函数,而且支持OrgDb收录的所有物种。下面使用DOSE包中的geneList作为示例进行演示

library(clusterProfiler)
data(geneList, package="DOSE")
gene <- names(geneList)[abs(geneList) > 2]
head(gene)
## [1] "4312"  "8318"  "10874" "55143" "55388" "991"
ego <- enrichGO(gene          = gene,                universe      = names(geneList),                OrgDb         = org.Hs.eg.db,                ont           = "CC",                pAdjustMethod = "BH",                pvalueCutoff  = 0.01,                qvalueCutoff  = 0.05,                readable      = TRUE)
#将输入基因转为Symbolhead(ego)#因为有一些Symbol对应多个ENSEMBL,可以直接用ID进行富集分析gene.df <- bitr(gene, fromType = "ENTREZID",        toType = c("ENSEMBL", "SYMBOL"),        OrgDb = org.Hs.eg.db)
ego2 <- enrichGO(gene         = gene.df$ENSEMBL,                OrgDb         = org.Hs.eg.db,                keyType       = 'ENSEMBL',                ont           = "CC",                pAdjustMethod = "BH",                pvalueCutoff  = 0.01,                qvalueCutoff  = 0.05)head(ego2, 3)  
#下面就是新增的GSEA富集分析了,需要同时输入基因名和变化倍数ego3 <- gseGO(geneList     = geneList,              OrgDb        = org.Hs.eg.db,              ont          = "CC",              minGSSize    = 100,#限制最少基因数              maxGSSize    = 500,#限制最多基因数              pvalueCutoff = 0.05,              verbose      = FALSE)
#最后就是将富集的通路做一个有向无环图进行可视化了
goplot(ego)
image

从这个图中我们可以去除冗余通路的信息,找到关键通路的上下游,从而更准确的定位到关键信号通路。


KEGG富集分析

KEGG相对于GO更加准确囊括了最关键的通路信息,在很多情况下都是我们最想关注的通路信号,下面就演示一下KEGG的通路富集分析。

data(geneList, package="DOSE")
gene <- names(geneList)[abs(geneList) > 2]
kk <- enrichKEGG(gene         = gene,                 organism     = 'hsa',                 pvalueCutoff = 0.05)
head(kk)

kk2 <- gseKEGG(geneList     = geneList,               organism     = 'hsa',               minGSSize    = 120,               pvalueCutoff = 0.05,               verbose      = FALSE)
head(kk2)

#上面两个是和GO富集分析一样的常规操作,对于KEGG,还增添了对通路的模块分析,这对揭示一些功能单元有更直接的效果。
mkk <- enrichMKEGG(gene = gene,                   organism = 'hsa',                   pvalueCutoff = 1,                   qvalueCutoff = 1)
head(mkk)                   
mkk2 <- gseMKEGG(geneList = geneList,                 organism = 'hsa',                 pvalueCutoff = 1)
head(mkk2)
#KEGG富集分析的可视化
browseKEGG(kk, 'hsa04110')

#BiocManager::install("pathview")
library("pathview")
hsa04110 <- pathview(gene.data  = geneList,                     pathway.id = "hsa04110",                     species    = "hsa",                     limit      = list(gene=max(abs(geneList)), cpd=1))

比如我们想研究hsa04110(Cell cycle)这个通路,通过对关键通路进行可视化我们可以找到差异变化的基因在通路中的位置和作用。

image
image

其它通路富集分析

GO和KEGG是我们最常用的基因集,但是还有一些其它揭示细胞某些特征的基因集,如:WikiPathways,Reactome,Mesh和Disease等,在新版本的clusterProfiler 4都可以基于以上基因集进行富集分析。

#------------------WikiPathways----------------
data(geneList, package="DOSE")
gene <- names(geneList)[abs(geneList) > 2]
enrichWP(gene, organism = "Homo sapiens") 
gseWP(geneList, organism = "Homo sapiens")
#---------------------Reactome------------------
library(ReactomePA)
data(geneList, package="DOSE")
de <- names(geneList)[abs(geneList) > 1.5]
head(de)
x <- enrichPathway(gene=de, pvalueCutoff = 0.05, readable=TRUE)

y <- gsePathway(geneList,                 pvalueCutoff = 0.2,                pAdjustMethod = "BH",                 verbose = FALSE)
#可视化
viewPathway("E2F mediated regulation of DNA replication",             readable = TRUE,             foldChange = geneList)

#---------------------Mesh------------------
library(meshes)
data(geneList, package="DOSE")
de <- names(geneList)[1:100]
x <- enrichMeSH(de, MeSHDb = db, database='gendoo', category = 'C')
y <- gseMeSH(geneList, MeSHDb = db, database = 'gene2pubmed', category = "G")

#---------------------Disease------------------
library(DOSE)
data(geneList)gene <- names(geneList)[abs(geneList) > 1.5]
head(gene)
x <- enrichDO(gene          = gene,              ont           = "DO",              pvalueCutoff  = 0.05,              pAdjustMethod = "BH",              universe      = names(geneList),              minGSSize     = 5,              maxGSSize     = 500,              qvalueCutoff  = 0.05,              readable      = FALSE)              
y <- gseDO(geneList,           minGSSize     = 120,           pvalueCutoff  = 0.2,           pAdjustMethod = "BH",           verbose       = FALSE)

#专门对癌基因进行富集分析
gene2 <- names(geneList)[abs(geneList) < 3]
ncg <- enrichNCG(gene2) head(ncg)

EnrichR富集分析

上述提到的基因集都是非常经典的基因集,而在实际应用中我们还需要对基于自己数据构建的基因集进行富集分析,clusterProfiler 4的EnrichR函数就能实现这个目的。

data(geneList, package="DOSE")
head(geneList)
##     4312     8318    10874    55143    55388      991
## 4.572613 4.514594 4.418218 4.144075 3.876258 3.677857
gene <- names(geneList)[abs(geneList) > 2]
head(gene)
## [1] "4312"  "8318"  "10874" "55143" "55388" "991"
#cell marker
cell_marker_data <- vroom::vroom('http://bio-bigdata.hrbmu.edu.cn/CellMarker/download/Human_cell_markers.txt')
## instead of `cellName`, users can use other features (e.g. `cancerType`)
cells <- cell_marker_data %>%    dplyr::select(cellName, geneID) %>%    dplyr::mutate(geneID = strsplit(geneID, ', ')) %>%    tidyr::unnest()x <- enricher(gene, TERM2GENE = cells)
y <- GSEA(geneList, TERM2GENE = cells)

多组平行样本间的比较

要说这次更新最大的亮点,就是接下来要说的多组平行样本间的富集分析。对于一般只有两组实验(实验组和对照组),我们只需要计算出差异基因直接进行富集分析即可。但是实际实验中,如药物处理的样本,我们往往会设置多个梯度的平行分组,如何同时对所有组直接进行比较,clusterProfiler 4给出了完美的解决方式。

data(gcSample)
str(gcSample) 
#这里有8组数据## List of 8
##  $ X1: chr [1:216] "4597" "7111" "5266" "2175" ...##  $ X2: chr [1:805] "23450" "5160" "7126" "26118" ...##  $ X3: chr [1:392] "894" "7057" "22906" "3339" ...##  $ X4: chr [1:838] "5573" "7453" "5245" "23450" ...##  $ X5: chr [1:929] "5982" "7318" "6352" "2101" ...##  $ X6: chr [1:585] "5337" "9295" "4035" "811" ...##  $ X7: chr [1:582] "2621" "2665" "5690" "3608" ...##  $ X8: chr [1:237] "2665" "4735" "1327" "3192" ...

ck <- compareCluster(geneCluster = gcSample, fun = enrichKEGG)
ck <- setReadable(ck, OrgDb = org.Hs.eg.db, keyType="ENTREZID")
mydf <- data.frame(Entrez=names(geneList), FC=geneList)
mydf <- mydf[abs(mydf$FC) > 1,]
mydf$group <- "upregulated"
mydf$group[mydf$FC < 0] <- "downregulated"
mydf$othergroup <- "A"
mydf$othergroup[abs(mydf$FC) > 2] <- "B"
formula_res <- compareCluster(Entrez~group+othergroup, data=mydf, fun="enrichKEGG")  
head(formula_res)
#对结果进行可视化
dotplot(ck)
dotplot(formula_res)
image
image

如果你觉得这样不方便观察,还可以分开作图

dotplot(formula_res, x="group") + facet_grid(~othergroup)
image
#我们还可以对所有基因做一个网状图
cnetplot(ck)
image

可视化分析汇总

上面对clusterProfiler 4所有的功能做了个简要的介绍,大家还可以通过阅读原文去深入学习。最后我们对新版的clusterProfiler的可视化功能做一个总结。

library(DOSE)
data(geneList)
de <- names(geneList)[abs(geneList) > 2]
edo <- enrichDGN(de)
library(enrichplot)
barplot(edo, showCategory=20) mutate(edo, qscore = -log(p.adjust, base=10)) %>%     barplot(x="qscore")
image
image
## convert gene ID to Symbol
edox <- setReadable(edo, 'org.Hs.eg.db', 'ENTREZID')
p1 <- cnetplot(edox, foldChange=geneList)## categorySize can be scaled by 'pvalue' or 'geneNum'
p2 <- cnetplot(edox, categorySize="pvalue", foldChange=geneList)
p3 <- cnetplot(edox, foldChange=geneList, circular = TRUE, colorEdge = TRUE) 
p1|p2|p3
image
p1 <- cnetplot(edox, node_label="category",         cex_label_category = 1.2) 
p2 <- cnetplot(edox, node_label="gene",         cex_label_gene = 0.8) 
p3 <- cnetplot(edox, node_label="all") 
p4 <- cnetplot(edox, node_label="none",         color_category='firebrick',         color_gene='steelblue') 
cowplot::plot_grid(p1, p2, p3, p4, ncol=2, labels=LETTERS[1:4])
image
set.seed(123)
x <- list(A = letters[1:10], B=letters[5:12], C=letters[sample(1:26, 15)])
p1 <- cnetplot(x)set.seed(123)d <- setNames(rnorm(26), letters)
p2 <- cnetplot(x, foldChange=d) +     scale_color_gradient2(name='associated data', low='darkgreen', high='firebrick')
cowplot::plot_grid(p1, p2, ncol=2, labels=LETTERS[1:2])    
image
p1 <- heatplot(edox, showCategory=5)
p2 <- heatplot(edox, foldChange=geneList, showCategory=5)
cowplot::plot_grid(p1, p2, ncol=1, labels=LETTERS[1:2])
image
edox2 <- pairwise_termsim(edox)
p1 <- treeplot(edox2)
p2 <- treeplot(edox2, hclust_method = "average")
aplot::plot_list(p1, p2, tag_levels='A')
image
edo <- pairwise_termsim(edo)
p1 <- emapplot(edo)
p2 <- emapplot(edo, cex_category=1.5)
p3 <- emapplot(edo, layout="kk")
p4 <- emapplot(edo, cex_category=1.5,layout="kk") 
cowplot::plot_grid(p1, p2, p3, p4, ncol=2, labels=LETTERS[1:4])
image
library(clusterProfiler)
data(gcSample)
xx <- compareCluster(gcSample, fun="enrichKEGG",                     organism="hsa", pvalueCutoff=0.05)xx <- pairwise_termsim(xx)                     
p1 <- emapplot(xx)
p2 <- emapplot(xx, legend_n=2) 
p3 <- emapplot(xx, pie="count")
p4 <- emapplot(xx, pie="count", cex_category=1.5, layout="kk")
cowplot::plot_grid(p1, p2, p3, p4, ncol=2, labels=LETTERS[1:4])
image
upsetplot(edo)
image
upsetplot(kk2) 
image
ridgeplot(edo2)
image
p1 <- gseaplot(edo2, geneSetID = 1, by = "runningScore", title = edo2$Description[1])
p2 <- gseaplot(edo2, geneSetID = 1, by = "preranked", title = edo2$Description[1])
p3 <- gseaplot(edo2, geneSetID = 1, title = edo2$Description[1])
cowplot::plot_grid(p1, p2, p3, ncol=1, labels=LETTERS[1:3])
image
gseaplot2(edo2, geneSetID = 1, title = edo2$Description[1])
image
gseaplot2(edo2, geneSetID = 1:3)
image
p1 <- gseaplot2(edo2, geneSetID = 1:3, subplots = 1)
p2 <- gseaplot2(edo2, geneSetID = 1:3, subplots = 1:2)
cowplot::plot_grid(p1, p2, ncol=1, labels=LETTERS[1:2])
image
library(ggplot2)
library(cowplot)
pp <- lapply(1:3, function(i) {    anno <- edo2[i, c("NES", "pvalue", "p.adjust")]    lab <- paste0(names(anno), "=",  round(anno, 3), collapse="\n")    gsearank(edo2, i, edo2[i, 2]) + xlab(NULL) +ylab(NULL) +        annotate("text", 10000, edo2[i, "enrichmentScore"] * .75, label = lab, hjust=0, vjust=0)})plot_grid(plotlist=pp, ncol=1)
image
terms <- edo$Description[1:5]
p <- pmcplot(terms, 2010:2020)
p2 <- pmcplot(terms, 2010:2020, proportion=FALSE)
plot_grid(p, p2, ncol=2)
image

小结

高通量组学数据功能解读中,功能富集分析是至关重要的一步,相关软件繁多但大多数仅针对极少量的模式生物开发,无法支持大量非模式生物的分析诉求。功能分析依赖准确的功能注释,但许多软件在发表文章之后并未及时更新内置的功能注释。2016年,Nature Methods文章指出,高达42%的相关工具内置注释超过五年未更新,用户基于此类工具的数据挖掘,结论反应的仅是学界五年前的生物学知识积累,颇有时光倒流的感觉。尤为重要的是,基于旧有注释,大约只能捕获到最新数据库中26%的生物学过程或通路。

ClusterProfiler 4相对于前一版不仅更新了参考基因集,而且新加入了很多功能,如GSEA分析、DO富集分析以及多组间样本的平行比较等。新版本尤其实现多组数据间自由比较,如不同条件、处理等,并内置系列流行辅助工具,如数据处理包dplyr、可视化包ggplot2等,方便分析人员用熟悉的方式自由探索,实现数据高效解读。目前,clusterProfiler已被整合进超过30个的同行分析软件中,致力于解决不同场景下的功能分析,相信clusterProfiler4.0未来将发挥更大的作用,助力研究者更高效地解读生物医学数据及建立更可靠的机制假说。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容