目录

  • 1.中性理论原理介绍
  • 2. R语言实现
  • 3. 参考文献
  • 4. 其它推断群落构建的方法
  • 5. 测试文件与R代码及运行效果

  许多SCI文章都使用了一种叫NCM的方法来对微生物群落构建(中性理论 or 生态位理论?)进行预测,本文将对NCM的实现原理及其R实现做介绍。在介绍其原理的过程中会有一些数学公式,不要对这些数学公式产生抵触情绪,我会解释其每一项的生态学含义。与原理相比,其R实现则相对简单,阅读完后可将原理与R实现进行对比。

1.中性理论原理介绍

In order for an assemblage to change, an individual must die or leave the system. It is then immediately replaced by an individual either by a birth from within the community or by an immigrant from a source community

只有当物种死亡或离开这个系统时,群落结构才会发生改变。此时,离开个体的生态位就会空余出来,其它个体会通过来自群落外的迁移群落内部的繁殖来填补空出的生态位。因此可以把群落的动态描述为死亡——繁殖/扩散——死亡这样的循环。
  根据上述的原理,如果我知道 t0 时刻:

  • 物种 i 的在本地群落(local community)内的个体数为 NiN_iNi​ ,即OTU table(行名:sample ID,列名:species ID)中的每个单元格的数字
  • 物种 i 在宏群落(meta-community)内的相对丰度为 pip_ipi​,即OTU table中列的和/OTU表的和
  • 该本地群落(local community)总的个体数为 NTN_TNT​,即OTU table中行的和
  • 个体死亡后被宏群落中的物种替换的概率为 mmm
  • 物种 i 的繁殖率与所有物种的平均繁殖率的比值 αi\alpha_iαi​

群落中1个个体(individual)死亡时,我们记此时的时间为 t1。此时会有以下几种可能:

  • 可能1: 死亡的是物种 i 。其概率为: Ni/NTN_i/N_TNi​/NT​

    • 可能1.1: 物种 i 的个体死亡后空余的生态位被群落内的物种通过繁殖的方式取代。其概率为: 1−m1-m1−m

      • 可能1.1.1: 被群落内相同的物种取代。其概率为: (1+αi)(Ni−1)/(NT−1)(1+\alpha_i)(N_i-1)/(N_T - 1)(1+αi​)(Ni​−1)/(NT​−1)
      • 可能1.1.2: 被群落内不相同的物种取代。其概率为: (1−αi)(NT−Ni)/(NT−1)(1-\alpha_i)(N_T - N_i)/(N_T - 1)(1−αi​)(NT​−Ni​)/(NT​−1)
    • 可能1.2: 物种 i 的个体死亡后空余的生态位被群落外的物种通过扩散的方式取代。其概率为: mmm
      • 可能1.2.1: 被群落外相同的物种取代。其概率为: pip_ipi​
      • 可能1.2.2: 被群落外不相同的物种取代。其概率为: 1−pi1 - p_i1−pi​
  • 可能2: 死亡的不是物种 i。其概率为: (NT−Ni)/NT(N_T - N_i)/N_T(NT​−Ni​)/NT​
    • 可能2.1: 非物种 i 的个体死亡后空余的生态位被群落内的物种通过繁殖的方式取代。 其概率为: 1−m1 - m1−m

      • 可能2.1.1: 被群落内的物种 i 取代。(1+αi)Ni/(NT−1)(1+\alpha_i)N_i/(N_T - 1)(1+αi​)Ni​/(NT​−1)
      • 可能2.1.2: 被群落内的非物种 i 取代。(1−αi)(NT−Ni−1)/(NT−1)(1-\alpha_i)(N_T - N_i - 1)/(N_T - 1)(1−αi​)(NT​−Ni​−1)/(NT​−1)
    • 可能2.2: 非物种 i 的个体死亡后空余的生态位被群落外的物种通过扩散的方式取代。其概率为: mmm
      • 可能2.2.1: 被群落外的物种 i 取代。pip_ipi​
      • 可能2.2.2: 被群落外的非物种 i 取代。1−pi1 - p_i1−pi​

那么,与 t0 时刻相比 t1 时刻物种 i 的数量可能:减少 1个、不变和增加一个,即 t1 时刻物种 i 的数量可能为:Ni−1N_i-1Ni​−1、NiN_iNi​和Ni+1N_i+1Ni​+1,其可能的概率如下:

物种 i 增加一个的概率 = 可能2 * (可能2.1 * 可能2.1.1 + 可能2.2 * 可能2.2.1)物种 i 不变的概率 = 可能1 * (可能1.1 * 可能1.1.1 + 可能1.2 * 可能1.2.1)+ 可能2 * (可能2.1 * 可能2.1.2 + 可能2.2 * 可能2.2.2)物种 i 减少一个的概率 = 可能1 * (可能1.1 * 可能1.1.2 + 可能1.2 * 可能1.2.2)

写成数学表达式就是文献中的公式了:

但我认为文献中的公式有点小问题,我认为应该是下面的公式,与文献的公式有些出入,我用红色标出来了

  • Pr(Ni+1Ni)=(NT−NiNT)[mpi+(1+αi)(1−m)(NiNT−1)Pr(\frac{N_i+1}{N_i})=(\frac{N_T-N_i}{N_T})[mp_i+(1+\alpha_i)(1-m)(\frac{N_i}{N_T-1})Pr(Ni​Ni​+1​)=(NT​NT​−Ni​​)[mpi​+(1+αi​)(1−m)(NT​−1Ni​​)

  • Pr(NiNi)=NiNT[mpi+(1+αi)(1−m)(Ni−1NT−1)]+(NT−NiNT)[m(1−pi)+(1−αi)(1−m)(NT−Ni−1NT−1)]Pr(\frac{N_i}{N_i})=\frac{N_i}{N_T}[mp_i+\textcolor{red}{(1+\alpha_i)}(1-m)(\frac{N_i-1}{N_T-1})]+(\frac{N_T-N_i}{N_T})[m(1-p_i)+\textcolor{red}{(1-\alpha_i)}(1-m)(\frac{N_T-N_i-1}{N_T-1})]Pr(Ni​Ni​​)=NT​Ni​​[mpi​+(1+αi​)(1−m)(NT​−1Ni​−1​)]+(NT​NT​−Ni​​)[m(1−pi​)+(1−αi​)(1−m)(NT​−1NT​−Ni​−1​)]

  • Pr(Ni−1Ni)=NiNT[m(1−pi)+(1−αi)(1−m)(NT−NiNT−1)]Pr(\frac{N_i-1}{N_i})=\frac{N_i}{N_T}[m(1-p_i)+(1-\alpha_i)(1-m)(\frac{N_T-N_i}{N_T-1})]Pr(Ni​Ni​−1​)=NT​Ni​​[m(1−pi​)+(1−αi​)(1−m)(NT​−1NT​−Ni​​)]

这个公式的意义就是当我们知道 t0 时刻的物种 i 的丰度时,我们就可以推断下一时刻 t1 时物种 i 的可能的数量。此时,令xi=Ni/NTx_i=N_i/N_Txi​=Ni​/NT​,及xix_ixi​表示物种 i 的相对丰度。根据forward Kolmogorov equation,xix_ixi​在 t 时刻的概率密度函数为: xix_ixi​的概率密度ϕi(xi,t)\phi_i(x_i,t)ϕi​(xi​,t)随时间 t 的变化为:


MδxM_{\delta x}Mδx​和VδxV_{\delta x}Vδx​ 中MMM表示期望,VVV表示方差,δx\delta xδx表示x的变化量。因此 MδxM_{\delta x}Mδx​ 表示物种 i 相对丰度变化量的期望, VδxV_{\delta x}Vδx​表示物种 i 相对丰度变化量的方差。因此:

Mδx=1∗Pr(Ni+1Ni)+(−1)∗Pr(Ni−1Ni)M_{\delta x}=1 * Pr(\frac{N_i+1}{N_i})+(-1)*Pr(\frac{N_i-1}{N_i})Mδx​=1∗Pr(Ni​Ni​+1​)+(−1)∗Pr(Ni​Ni​−1​)

Vδx=1∗Pr(Ni+1Ni)+1∗Pr(Ni−1Ni)V_{\delta x}=1 * Pr(\frac{N_i+1}{N_i})+1*Pr(\frac{N_i-1}{N_i})Vδx​=1∗Pr(Ni​Ni​+1​)+1∗Pr(Ni​Ni​−1​)

可得:

这里VδxV_{\delta x}Vδx​与MδxM_{\delta x}Mδx​相比可以忽略不计,因为NTN_TNT​在OTU表中每个样点往往有成千上万条序列,即NT>1000N_T>1000NT​>1000,而0<xi<10<x_i<10<xi​<1以0<pi−xi<10<p_i-x_i<10<pi​−xi​<1。

且∂ϕ∂x=0\frac{ \partial \phi }{\partial x} = 0∂x∂ϕ​=0,获得ϕi\phi_iϕi​的结果为


该分布是一个beta分布的概率密度函数。物种 i 占居的频率(occurrence frequency: row sums of binary OTU table/number of sites)为其概率密度函数的积分。

此时该分布是一个beta分布,我们就可以在R语言中利用beta分布对其进行拟合,获得参数m的评估值。

2. R语言实现

##Fits the neutral model from Sloan et al. 2006 to an OTU table and returns several fitting statistics. Alternatively, will return predicted occurrence frequencies for each OTU based on their abundance in the metacommunity
#Install the following packages if they haven't been availabled in your computer yet
library(Hmisc)
library(minpack.lm)
library(stats4)
#using Non-linear least squares (NLS) to calculate R2:
#spp: A community table with taxa as rows and samples as columns
spp<-read.csv('spp.txt',head=T,stringsAsFactors=F,row.names=1,sep = "\t")
spp<-t(spp)
#get the mean of abundance of each sample
N <- mean(apply(spp, 1, sum))
#get the mean of species relative abundance in metacommmunity
p.m <- apply(spp, 2, mean)
p.m <- p.m[p.m != 0]
#get the percentage of each species in metacommmunity
p <- p.m/N
#get the binary data of community abundance matrix
spp.bi <- 1*(spp>0)
#get the frequncy of species occurrence in metacommunity
freq <- apply(spp.bi, 2, mean)
freq <- freq[freq != 0]
#get a table record species percentage and occurrence frequency in metacommunity
C <- merge(p, freq, by=0)
#sort the table according to occurence frquency of each species
C <- C[order(C[,2]),]
C <- as.data.frame(C)
#delete rows containning zero
C.0 <- C[!(apply(C, 1, function(y) any(y == 0))),]
p <- C.0[,2]
freq <- C.0[,3]
names(p) <- C.0[,1]
names(freq) <- C.0[,1]
d = 1/N
##Fit model parameter m (or Nm) using Non-linear least squares (NLS)
m.fit <- nlsLM(freq ~ pbeta(d, N*m*p, N*m*(1 -p), lower.tail=FALSE),start=list(m=0.1))
m.fit #get the m value
m.ci <- confint(m.fit, 'm', level=0.95)
freq.pred <- pbeta(d, N*coef(m.fit)*p, N*coef(m.fit)*(1 -p), lower.tail=FALSE)
pred.ci <- binconf(freq.pred*nrow(spp), nrow(spp), alpha=0.05, method="wilson", return.df=TRUE)
# get the R2 value
Rsqr <- 1 - (sum((freq - freq.pred)^2))/(sum((freq - mean(freq))^2))
Rsqr#data visulization
#Drawing the figure using grid package:
#p is the mean relative abundance
#freq is occurrence frequency
#freq.pred is predicted occurrence frequency
bacnlsALL <-data.frame(p,freq,freq.pred,pred.ci[,2:3])
inter.col<-rep('black',nrow(bacnlsALL))
inter.col[bacnlsALL$freq <= bacnlsALL$Lower]<-'#A52A2A'#define the color of below points
inter.col[bacnlsALL$freq >= bacnlsALL$Upper]<-'#29A6A6'#define the color of up points
library(grid)
grid.newpage()
pushViewport(viewport(h=0.6,w=0.6))
pushViewport(dataViewport(xData=range(log10(bacnlsALL$p)), yData=c(0,1.02),extension=c(0.02,0)))
grid.rect()
grid.points(log10(bacnlsALL$p), bacnlsALL$freq,pch=20,gp=gpar(col=inter.col,cex=0.7))
grid.yaxis()
grid.xaxis()
grid.lines(log10(bacnlsALL$p),bacnlsALL$freq.pred,gp=gpar(col='blue',lwd=2),default='native')grid.lines(log10(bacnlsALL$p),bacnlsALL$Lower ,gp=gpar(col='blue',lwd=2,lty=2),default='native')
grid.lines(log10(bacnlsALL$p),bacnlsALL$Upper,gp=gpar(col='blue',lwd=2,lty=2),default='native')
grid.text(y=unit(0,'npc')-unit(2.5,'lines'),label='Mean Relative Abundance (log10)', gp=gpar(fontface=2))
grid.text(x=unit(0,'npc')-unit(3,'lines'),label='Frequency of Occurance',gp=gpar(fontface=2),rot=90)
#grid.text(x=unit(0,'npc')-unit(-1,'lines'), y=unit(0,'npc')-unit(-15,'lines'),label='Mean Relative Abundance (log)', gp=gpar(fontface=2))
#grid.text(round(coef(m.fit)*N),x=unit(0,'npc')-unit(-5,'lines'), y=unit(0,'npc')-unit(-15,'lines'),gp=gpar(fontface=2))
#grid.text(label = "Nm=",x=unit(0,'npc')-unit(-3,'lines'), y=unit(0,'npc')-unit(-15,'lines'),gp=gpar(fontface=2))
#grid.text(round(Rsqr,2),x=unit(0,'npc')-unit(-5,'lines'), y=unit(0,'npc')-unit(-16,'lines'),gp=gpar(fontface=2))
#grid.text(label = "Rsqr=",x=unit(0,'npc')-unit(-3,'lines'), y=unit(0,'npc')-unit(-16,'lines'),gp=gpar(fontface=2))
draw.text <- function(just, i, j) {grid.text(paste("Rsqr=",round(Rsqr,3),"\n","Nm=",round(coef(m.fit)*N)), x=x[j], y=y[i], just=just)#grid.text(deparse(substitute(just)), x=x[j], y=y[i] + unit(2, "lines"),#          gp=gpar(col="grey", fontsize=8))
}
x <- unit(1:4/5, "npc")
y <- unit(1:4/5, "npc")
draw.text(c("centre", "bottom"), 4, 1)

3. 参考文献

[1] https://github.com/Weidong-Chen-Microbial-Ecology/Stochastic-assembly-of-river-microeukaryotes

[2] Quantifying the roles of immigration and chance in
shaping prokaryote community structure

4. 其它推断群落构建的方法

  • R语言并行计算beta-NTI代码和测试文件
  • R语言并行计算RCbray-curtis距离
  • R语言并行计算beta多样性零偏差值

5. 测试文件与R代码及运行效果

  • 测试文件及代码:Sloan中性群落模型测试文件及R代码
  • 运行效果:测试文件运行效果预览
  • 更多R语言分析微生物生态学的资源可参考如下链接:
    https://mianbaoduo.com/o/works/240342

Sloan中性群落模型(NCM)推断群落构建原理及其R实现相关推荐

  1. 在线作图|两分钟在线做中性群落模型分析

    中性群落模型 中性理论是过去十年中生态学核心理论的重大突破之一.中性理论考虑同域的竞争相似资源的营养相似物种.完全抛弃了如竞争优势等物种特性,甚至认为不同物种是功能等值的.模型假设群落中所有种有关这些 ...

  2. 距离矢量算法matlab实现,一种基于最小费用距离模型的城市生态网络构建方法与流程...

    本发明涉及生态网络构建技术领域,特别是涉及一种城市网络的构建方法. 背景技术: 最小费用距离是网络分析的一种计算方法,这种方法被用于物种保护.自然保护区功能规划.动物栖息地的确定.区域生态安全格局设计 ...

  3. 机器学习基础(七):概率图模型(HMM、MRF、CRF、话题模型、推断方法)

    7.概率图模型 概率模型probabilistic model:提供一种描述框架,将学习任务归结于计算变量的概率分布,核心是如何基于可观测变量推测出未知变量的条件分布 → ①生成式generative ...

  4. 模型训练平台的构建_用5行代码构建自定义训练的对象检测模型

    模型训练平台的构建 如今,机器学习和计算机视觉已成为一种热潮. 我们都已经看到了有关自动驾驶汽车和面部识别的新闻,并且可能想象到建立我们自己的计算机视觉模型将会多么酷. 但是,进入该领域并不总是那么容 ...

  5. R语言构建xgboost模型:使用xgboost构建广义线性模型(GLM):使用gblinear算法拟合线性模型并配置L1和L2正则化

    R语言构建xgboost模型:使用xgboost构建广义线性模型(GLM):使用gblinear算法拟合线性模型并配置L1和L2正则化 目录

  6. R语言构建xgboost模型:使用xgboost构建泊松回归(poisson regression)模型

    R语言构建xgboost模型:使用xgboost构建泊松回归(poisson regression)模型 目录 R语言构建xgboost模型:使用xgboost构建泊松回归(poisson regre ...

  7. DataScience:风控场景之金融评分卡模型的简介、构建(逻辑回归)开发(转评分卡)、使用过程(线上实现)之详细攻略

    DataScience:风控场景之金融评分卡模型的简介.构建(逻辑回归)&开发(转评分卡).使用过程(线上实现)之详细攻略 目录 逻辑回归之金融评分卡模型的简介.构建.开发.使用过程 1.金融 ...

  8. [Python人工智能] 三十四.Bert模型 (3)keras-bert库构建Bert模型实现微博情感分析

    从本专栏开始,作者正式研究Python深度学习.神经网络及人工智能相关知识.前一篇文章开启了新的内容--Bert,首先介绍Keras-bert库安装及基础用法及文本分类工作.这篇文章将通过keras- ...

  9. 指标体系|四个模型教会你指标体系构建的方法

    作为数据分析师,构建数据指标体系是较为基础但是极为重要的工作内容.好的指标体系能够监控业务变化,当业务出现问题时,分析师们通过指标体系进行问题回溯和下钻能够准确地定位到问题,反馈给业务让其解决相应的问 ...

最新文章

  1. PortableApps的使用方法
  2. Eclipse设置字体
  3. DBSNMP和SYSMAN用户初始密码及正确的修改方式
  4. 【BZOJ 3036】 3036: 绿豆蛙的归宿 (概率DP)
  5. oracle中更改列明和更改显示列长度
  6. java西游记壹_岩浆数码再现手机RPG游戏--西游记壹
  7. linux vim(gvim) 多标签页,Vim 的标签页功能
  8. zxing二维码生成工具类
  9. C/C++静态库编译报错(/usr/bin/ld:cannot find -lpthread,/usr/bin/ld:cannot find -lc)
  10. 编辑框已经获取了焦点,输入法不自动弹起
  11. python爬虫框架源码_python爬虫的基本框架
  12. 入行Web前端的学习方法有哪些?
  13. docker 环境下通过ocelot和consul 实现服务发现与自治
  14. 8位可控加减法电路设计_C++手撕底层:位、字节、原码、反码、补码的深入理解...
  15. 九、Oracle学习笔记:聚合函数
  16. Vue使用阿里iconfont图标
  17. 夏普电视服务器维修,夏普液晶电视机通病维修方法
  18. 英语3500词(三)professions主题 (2022.1.15)
  19. java comp_java:comp / env /做什么?
  20. 基于139邮箱的新邮件到达免费短信提醒的研究与应用

热门文章

  1. 物联平台纷争,能否拯救智能硬件?
  2. 我的世界服务器披风文件在哪,关于我的世界国际版披风导入方法与详解(联机可用...
  3. 怎么用计算机解开手机,怎么用手机解锁电脑?用手机指纹解锁电脑图文教程
  4. 技术的真相 | 从AR口红试妆了解人工智能试妆技术
  5. 教你如何轻松解密Md5密码
  6. h5 苹果IOS端 播放mp3 没声音
  7. python中引号的使用规范_Python中单引号和双引号的作用
  8. 能定位的不仅GPS,还有它!
  9. oss视频转码处理(解决部分浏览器无法正常播放问题)
  10. 王者荣耀 微信登录 服务器找不到,王者荣耀微信无法登录是怎么回事 具体解决方法...