查看原文
其他

Science组合图表解读

陈威 宏基因组 2022-07-05
作者

陈威,水利部中国科学院水工程生态研究所,藻类生态学方向,R语言爱好者。

关于此图的讨论已经有一段时间了。我发现一个事实,对此图教程表现出强烈渴望的小伙伴名字后面都有“生态”二字。不管是土壤生态、草地生态还是水生态。非生态的大佬及吃瓜群众也被图形的美学及提供的丰富信息量所吸引。R小白的我也尝试着去还原文中的美图,但是一直进展缓慢。这几天,擂台赛似的相继出来了几种画法:“坐标法”,“python法”(原谅我也不知道用的什么法),“拼接法”,原图的效果大致都出来了:

R语言之照猫画虎1

R语言之照猫画虎2

但是有几位大佬好像把mantel test的mantel拼错了。于是乎,我决定以文献原文为基础,尝试结合corrplot和mantel test讲一个小故事。先结合图表简单介绍一下原文。题目:基于浮游动物群落揭示氨氮的生态阈值

图1,左下角展示了13种环境因子之间的相关性,右上角展示了浮游动物zooplankton(包括枝角类cladocera,桡足类copepod和轮虫rotiffer,其实还应该有原生动物,不知道这里为什么没有提),以及3个subsample枝角类,桡足类和轮虫群落与每一个环境因子之间的mantel 相关性。


回到图中左下部分,可以看出,总氮TN与硝氮NO3(,氨氮TAN(均为总氮的一部分)相关性非常高,化学需氧量CODMn和生物需氧量BOD5相关性非常高,还有其他。其实,首先应该试探性将所有环境因子作为解释变量进行初步分析,查看其方差膨胀因子(variance inflation factor,VIF)大小, 一般认为 VIF>10时,因子间共线性明显,需对其缩减,原则为pearson相关系数大于0.75的所有因子只保留其中一个,具体选择过程就不赘述了。

回到图中右上部分,可以看出,与浮游动物总群落相关性较高的有TN,PO4,TAN(这三者的自相关也非常高,可以认为是一个因子吗?)。TAN与浮游动物总群落和桡足类的相关性大于0.3,与枝角类的相关性在0.2~0.3,是所有环境因子里面最大的,我想这就是这篇文章主题的来源吧。

图2A,物种矩阵与环境矩阵的冗余分析(RDA),揭示环境因子对物种群落的影响。可以看出TAN的箭头处往第一轴上做垂线时,是最长的。此处与图1的结果吻合。图2B则单独拿出TAN含量与其样本在RDA第一轴上的得分做回归,相关系数当然高。

可以说,以上的所有内容只为找到这个TAN,剩下的内容就是拿TAN来做文章,此处就不说了。

回头看另一篇更早的文章,Structure and function of theglobal ocean microbiome,找出的关键因素是Temperature,套路几乎一模一样。

 

弄清楚了套路,接下来谈谈数据是怎么分析的,图是怎么画的吧。

1、首先得有两个矩阵,一个是物种矩阵,另一个是影响物种组成的环境因子矩阵,两个矩阵有相同的行名称(如果有的话)及行数量,且物种矩阵每一行的和不能为0,暂且分别命名为otu和env。

2、计算env矩阵的相关系数,并以图形的方式展示出来。

otu<-read.csv(“otu.csv”,head=T,row.names=1) #如果没有行名,则不需row.names=1env<-read.csv(“env.csv”,head=T,row.names=1) #如果没有行名,则不需row.names=1library(corrplot)rdf<-cor(env)
#得到相关矩阵图corrplot(rdf,method = "ellipse" ,type = "upper",addrect = 1,insig="blank",rect.col = "blue",rect.lwd = 2)

以上因子的排序是按照env中的原始排序。考虑到后面的操作,我们更愿意将相关性高的一类因子放在一起,因此可以加入参数order="AOE",另外"FPC","hclust"也有类似的效果。但是需要特别注意的是,后续mantel test 结果表中的因子顺序需按此重新排序,以免发生错配。

corrplot(cor(env),method = "ellipse",type = "upper",order="AOE",addrect = 1,insig="blank",rect.col = "blue",rect.lwd = 2)

为方便,本文还是以默认排序进行演示。

3、计算总类群及分类群与各个环境因子的mantel相关系数及显著性。

这一部分的内容感谢群里的李金明老师提供的方案,我做得有限。首先看封装的完整函数:

mt<-function(otu,env){+ library(vegan)+ library(dplyr)+ vars <- colnames(env)+ models<-list()+ for (i in seq_along(vars)){+ otu_bray<-vegdist(otu,method = "bray")+ env_dis<-vegdist(env[vars[i]],method = "euclidean")+ model <- mantel(otu_bray,env_dis, permutations=999)+ name <- vars[i]+ statistic <- model$statistic+ signif <- model$signif+ models[[i]] <- data.frame(name = name, statistic = statistic, signif = signif, row.names = NULL)+ }+ models %>% bind_rows()+ }

函数的功能大概就是将env矩阵中的每一个环境因子(已通过筛选)与otu进行mantel test,并从返回的model中将相关系数statistic和p值signif提取出来,并按顺序返回到一个新的dataframe中。此函数大大降低了工作量,只需作者整理好完整物种矩阵及各个subsample矩阵。当然也可以是多个独立的,但是都与同一环境因子矩阵相关联的物种矩阵,但是会损失一些可比信息。导入函数后,我们直接运行:

mantRpTotal<-mt(otu,env)
#不同subsample最好不要重合otu_sub1<-otu[,1:18]otu_sub2<-otu[,-(1:18)]
#同样必须保证otu_sub1和otu_sub2中每一行的和不为0mantRpTotal<-mt(otu,env)mantRpsub1<-mt(otu_sub1,env)mantRpsub2<-mt(otu_sub2,env)#得到三组相关矩阵
> mantRpTotalname statistic signif1 T 0.07099868 0.2772 Cond 0.21553934 0.0513 DO -0.03173941 0.5404 pH 0.30217734 0.0175 ORP -0.09269039 0.7966 Chla 0.10956145 0.196> mantRpsub1name statistic signif1 T 0.08162417 0.2572 Cond 0.21331172 0.0413 DO -0.08547460 0.7004 pH 0.26544007 0.0145 ORP -0.07304401 0.7446 Chla 0.15479697 0.101> mantRpsub2name statistic signif1 T 0.007865918 0.4462 Cond 0.177458987 0.1073 DO 0.012635374 0.4074 pH 0.291917464 0.0215 ORP -0.116943736 0.8536 Chla 0.044119183 0.332


利用此表做出文献图1中右上部分的线段图还不够,还需要另外输入坐标信息。此处参考厚蕴老师的方法。

set.seed(123)n <- ncol(env)grp <- c('Total', 'Sub1', 'Sub2') # 分组名称subx <- c(-2, -1, 0) # 分组的X坐标suby <- c(4.5, 2.5, 1) # 分组的Y坐标
df <- data.frame(grp = rep(grp, each = n), # 分组名称,每个重复n次subx = rep(subx, each = n), # 组X坐标,每个重复n次suby = rep(suby, each = n), # 组Y坐标,每个重复n次x = rep(0:(n - 1) - 0.5, 3), # 变量连接点X坐标y = rep(n:1, 3), # 变量连接点Y坐标)> dfgrp subx suby x y1 Total -2 5.0 -0.5 62 Total -2 5.0 0.5 53 Total -2 5.0 1.5 44 Total -2 5.0 2.5 35 Total -2 5.0 3.5 26 Total -2 5.0 4.5 17 Sub1 -1 2.5 -0.5 68 Sub1 -1 2.5 0.5 59 Sub1 -1 2.5 1.5 410 Sub1 -1 2.5 2.5 311 Sub1 -1 2.5 3.5 212 Sub1 -1 2.5 4.5 113 Sub2 0 1.0 -0.5 614 Sub2 0 1.0 0.5 515 Sub2 0 1.0 1.5 416 Sub2 0 1.0 2.5 317 Sub2 0 1.0 3.5 218 Sub2 0 1.0 4.5 1df2 <-rbind(mantRpTotal, mantRpsub1, mantRpsub2)df_segment<-cbind(df,df2)df_segmentname statistic signif grp subx suby x y1 T 0.070998676 0.277 Total -2.0 4.5 -0.5 62 Cond 0.215539337 0.051 Total -2.0 4.5 0.5 53 DO -0.031739414 0.540 Total -2.0 4.5 1.5 44 pH 0.302177339 0.017 Total -2.0 4.5 2.5 35 ORP -0.092690387 0.796 Total -2.0 4.5 3.5 26 Chla 0.109561448 0.196 Total -2.0 4.5 4.5 17 T 0.081624169 0.257 Sub1 -1.0 2.5 -0.5 68 Cond 0.213311719 0.041 Sub1 -1.0 2.5 0.5 59 DO -0.085474598 0.700 Sub1 -1.0 2.5 1.5 410 pH 0.265440072 0.014 Sub1 -1.0 2.5 2.5 311 ORP -0.073044012 0.744 Sub1 -1.0 2.5 3.5 212 Chla 0.154796969 0.101 Sub1 -1.0 2.5 4.5 113 T 0.007865918 0.446 Sub2 0 1.0 -0.5 614 Cond 0.177458987 0.107 Sub2 0 1.0 0.5 515 DO 0.012635374 0.407 Sub2 0 1.0 1.5 416 pH 0.291917464 0.021 Sub2 0 1.0 2.5 317 ORP -0.116943736 0.853 Sub2 0 1.0 3.5 218 Chla  0.044119183  0.332  Sub2    0  1.0  4.5 1

4、此时需考虑线条美学的映射,按原文图的表示,并不是按数值大小完全映射,而是划分范围后映射,此处对此时的我来说是知识盲区,又一次参考厚蕴老师的案例。

df_segment <- df_segment %>% mutate(lcol = ifelse(signif <= 0.001, '#1B9E77', NA), # p值小于0.001时,颜色为绿色,下面依次类推lcol = ifelse(signif > 0.001 & signif <= 0.01, '#88419D', lcol),lcol = ifelse(signif > 0.01 & signif <= 0.05, '#A6D854', lcol),lcol = ifelse(signif > 0.05, '#B3B3B3', lcol),lwd = ifelse(statistic >= 0.3,6, NA), # statistic >= 0.3 时,线性宽度为6,下面依次类推lwd = ifelse(statistic >= 0.15 & statistic < 0.3, 3, lwd),lwd = ifelse(statistic < 0.15, 1, lwd)     )

5、一切就绪,开始拼图。

corrplot(cor(env),method = "ellipse",type = "upper", addrect = 1,insig="blank",rect.col = "blue",rect.lwd = 2)
segments(df_segment$subx, df_segment$suby, df_segment$x, df_segment$y, lty = 'solid', lwd = df_segment$lwd, col = df_segment$lcol, xpd = TRUE)

结果已经很明显了,pH就是我们要找的那个目标。下面继续完善图形内容。

points(subx, suby, pch = 24, col = 'blue', bg = 'blue', cex = 2, xpd = TRUE)
points(x,y,pch=21,col="red",bg="red",cex=1,xpd=TRUE)
text(subx - 0.5, suby, labels = grp, adj = c(0.8, 0.5), cex = 1.2, xpd = TRUE)

图例的内容我就不搬了。

 

6、下面继续挖掘并聚焦已经找到的目标,pH。

library(vegan)otu_rda<- rda(otu,env)summary(otu_rda)plot(otu_rda)
#获取各样本pH在RDA第一轴的坐标,然后与env$pH做散点图pH_sca<- otu_rda$CCA$QR$qr$pH

具体画法很简单,不赘述(不班门弄斧了)。

 

至此,上述图形就都完成了,小故事也讲完了,有不对地方敬请指出。

 

 

参考资料:

[1].  Yang, J., et al., Ecogenomics of ZooplanktonCommunity Reveals Ecological Threshold of Ammonia Nitrogen. Environ SciTechnol, 2017. 51(5): p. 3057-3064.

[2]Sunagawa, S., Coelho, L. P., Chaffron, S., Kultima, J.R., Labadie, K., Salazar, G., … & Bork, P. (2015). Structure and function of theglobal ocean microbiome. Science, 348(6237), 1261359-1261359.

[3]厚缊,诹图——照虎画猫site:http://houyun.xyz/post/20190421

猜你喜欢

10000+:菌群分析 宝宝与猫狗 梅毒狂想曲 提DNA发Nature Cell专刊 肠道指挥大脑

系列教程:微生物组入门 Biostar 微生物组  宏基因组

专业技能:学术图表 高分文章 生信宝典 不可或缺的人

一文读懂:宏基因组 寄生虫益处 进化树

必备技能:提问 搜索  Endnote

文献阅读 热心肠 SemanticScholar Geenmedical

扩增子分析:图表解读 分析流程 统计绘图

16S功能预测   PICRUSt  FAPROTAX  Bugbase Tax4Fun

在线工具:16S预测培养基 生信绘图

科研经验:云笔记  云协作 公众号

编程模板: Shell  R Perl

生物科普:  肠道细菌 人体上的生命 生命大跃进  细胞暗战 人体奥秘  

写在后面

为鼓励读者交流、快速解决科研困难,我们建立了“宏基因组”专业讨论群,目前己有国内外5000+ 一线科研人员加入。参与讨论,获得专业解答,欢迎分享此文至朋友圈,并扫码加主编好友带你入群,务必备注“姓名-单位-研究方向-职称/年级”。PI请明示身份,另有海内外微生物相关PI群供大佬合作交流。技术问题寻求帮助,首先阅读《如何优雅的提问》学习解决问题思路,仍未解决群内讨论,问题不私聊,帮助同行。

学习16S扩增子、宏基因组科研思路和分析实战,关注“宏基因组”

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存