画图拿p值来上色,基本上很多人没有注意p值的分布,除非是工具培养了习惯,比如说火山图,p值就被转换成-10*log10(pvalue),所有人就默认这样画,但换一个就不清不楚了。

如果是一个随机的东西,去做检验,那p值的分布也会相对比较均一,或者是比较正态,均值在0.5附近之类的。

这个我们都可以试一下的,拿随机的基因ID来搞个富集分析:

require(clusterProfiler)
data(geneList, package="DOSE")
 
set.seed(42)
de2 = sample(names(geneList), 200)
 
y = enrichGO(de2, OrgDb='org.Hs.eg.db')
plot(density(y@result$p.adjust, bw=0.01))

我们拿个差异基因来做富集的话,结果是不一样的。

de <- names(geneList)[1:200]
x = enrichGO(de, OrgDb='org.Hs.eg.db')
plot(density(x@result$pvalue, bw=0.01))

就会有比较多的很小的p值,是一个偏态分布。

比如我拿前面20条通路来画图,我们看一下p值的分布:

plot(x@result$pvalue[1:20])

这样拿去映射颜色的话,比如说红-蓝,结果就是尾部几个p值大点的是蓝色,其它的一片红色,区分不开。

我们取个对数看看:

plot(log10(x@result$pvalue[1:20]))

区分度就有了。我们从整体上看的话,p值小的就被拉开了,p值大的,会聚集。

plot(density(log10(x@result$pvalue), bw=0.01))

所以如果只是单纯地把p值映射到颜色,就会是下面这两个图这样子,一片红区分不开。这样的图相信大家经常看到。

所以我自己画图的时候,我是会对p值取对数来映射的。你看看我们2021年在The Innovation上发的clusterProfiler 4.0的文章,图全部是我操刀的。

这些图的颜色区分度是有的。而画图的代码我是有提供的。大家可能没注意到这个细节,也就没有去抄我的代码。

对于上面的x对象,你用dotplot()来画,出来的图是这样子的:

dotplot(x)

就是这样子红点多,且没有区分度。

你是可以进行变换的。

dotplot(x) + set_enrichplot_color(type='fill', transform='log10') 

出来的图就是这样子,有区分度了。

这个功能很多人可能不知道。enrichplot中不同的图,配色一致,我不想要在不同的函数里有差不多的设置颜色代码,于是就写了这个set_enrichplot_color来统一设置颜色。它还是蛮好用的。比如说我想把颜色换成以前经典的红-蓝配色。只需要指定colors=c("red", "blue")即可。

dotplot(x) + set_enrichplot_color(type='fill', transform='log10', colors=c("red", "blue"))

虽然长期以来,我们是可以对p值取对数的,但太多人不会用了,太多的图,都是一片红了。于是我决定在新的版本中,让取对数成为默认。所以如果你用了v>=1.29.2,那么你用dotplot(x)出来的,就是取了对数的p值进行颜色映射的。

你可能又会想,你全都要,新的默认你想要,旧的默认,你还想要,怎么办?简单,还是用set_enrichplot_color,你只要把transform="identity"传入即可。也就是:

dotplot(x) + set_enrichplot_color(type='fill', transform='identity')