目的

パッケージのロード

library(rEDM); packageVersion("rEDM") #"0.7.1"
## Warning: package 'rEDM' was built under R version 3.4.4
## [1] '0.7.1'
library(dplyr); packageVersion("dplyr") #"0.8.0.1"
## Warning: package 'dplyr' was built under R version 3.4.4
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
## [1] '0.8.0.1'

3種food chainモデル

#Rt+1 = Rt + bR*Rt*(1-Rt/K) - aC*Rt*Ct
#Ct+1 = Ct + bC*Ct*Rt - aP*Ct*Pt - cC*Ct
#Pt+1 = Pt + bP*Ct*Pt - c*Pt

bR=3; K=60; aC=0.02
R.f <- function(v){
  v[1, 1] + bR*(1-v[1, 1]/K)*v[1, 1] - aC*v[1, 1]*v[1, 2]
}

bC=1.2; cC=0.7; aP=0.01
C.f <- function(v){
  v[1, 2] + bC*aC*v[1, 2]*v[1, 1] - aP*v[1, 2]*v[1, 3] - cC*v[1, 2]
}

bP=0.25; cP=0.1
P.f <- function(v){
  v[1, 3] + bP*aP*v[1, 3]*v[1, 2] - cP*v[1, 3]
}

関数定義

##テスト時系列を作る関数
#増加率が正規分布でランダムにばらつく、これの大きさを操作できるようにする
#測定誤差は無いものとする

test.ts <- function(x) {
  g <- matrix(c(30, 30, 30),nrow=1,ncol=3)
  
  eR <- rnorm(300, 0, x)
  eC <- rnorm(300, 0, x)
  eP <- rnorm(300, 0, x)

  for (i in 1:299) {
    gn <- c(R.f(matrix(g[i, ], nrow=1))+eR[i+1], 
            C.f(matrix(g[i, ], nrow=1))+eC[i+1], 
            P.f(matrix(g[i, ], nrow=1))+eP[i+1])
    g <- rbind(g, gn)
  } # g:1列目にresource, 2列目にconsumer, 3列目にpredator, 300 時間ステップ分
  
  g <- cbind(g,rnorm(300,25,x)) #4列目に乱数の列であるzの動態を挿入
  dimnames(g) <- NULL
  g
}


##simplex projectionで埋め込み次元を決定する関数
simp_emb <- function(x){
  simp_x_res0 <- 
    simplex(x, E=1:10, lib=c(1, 50), pred=c(1, 50), silent=TRUE)
  simp_x_res0[which.min(simp_x_res0$rmse), "E"]
}

##Multivariate S-mapを任意の種xと種y2種で行う関数
mvar_smap2 <- function(v, x, y) {
  mlt_smap_res0 <- block_lnlp(cbind(v[,x], v[,y]), tp = 1, target_column = 1,
                              method = "s-map", theta = seq(1,10,by=0.1), silent = T)
  Tm <- mlt_smap_res0[which.min(mlt_smap_res0$rmse), "theta"]
  block_lnlp(cbind(v[,x], v[,y]), tp = 1, target_column = 1,
             method = "s-map", theta = Tm, save_smap_coefficients = T, silent = T)
}

##Multivariate S-mapを任意の種x,y,z3種で行う関数
mvar_smap3 <- function(v, x, y, z) {
  mlt_smap_res0 <- block_lnlp(cbind(v[,x], v[,y], v[,z]), tp = 1, target_column = 1,
                              method = "s-map", theta = seq(1,10,by=0.1), silent = T)
  Tm <- mlt_smap_res0[which.min(mlt_smap_res0$rmse), "theta"]
  block_lnlp(cbind(v[,x], v[,y], v[,z]), tp = 1, target_column = 1,
             method = "s-map", theta = Tm, save_smap_coefficients = T, silent = T)
}

##2変数multivariate S-mapをフル埋め込み(末尾入れ替え)で行う関数
mvar_smapE <- function(x, E){
  mvarts <- cbind(x[,1], x[,2])
  for (i in 1:(E-2)){
    mvarts <- cbind(mvarts, lag(x[,1], n=as.integer((1:(E-2))[i])))
  }
  mlt_smap_res0 <- block_lnlp(mvarts, tp = 1, target_column = 1,
                              method = "s-map", theta = seq(1,10,by=0.1), silent = T)
  Tm <- mlt_smap_res0[which.min(mlt_smap_res0$rmse), "theta"]
  block_lnlp(mvarts, tp = 1, target_column = 1,
             method = "s-map", theta = Tm, save_smap_coefficients = T, silent = T)
}

時系列の例

set.seed(1)
g <- test.ts(1)
subset.g <- g[201:300, ] #最初の200ステップは捨てる

par(ps=14, lwd=1.5, family="sans")
plot(subset.g[, 1], type="l", ylim=c(10, 50), ylab="Abundance", xlab="Time", xaxt="n")
lines(subset.g[, 2], type="l", ylim=c(10, 50), col="blue")
lines(subset.g[, 3], type="l", ylim=c(10, 50), col="red")
lines(subset.g[, 4], type="l", ylim=c(10, 50), lty=3)
axis(1, labels=c(200, 220, 240, 260, 280, 300), at=c(0, 20, 40, 60, 80, 100))
legend("bottomleft", 
       legend=c("Resource", "Consumer", "Predator", "Gaussian noise"), 
       col=c("black", "blue", "red", "black"), lty=c(1, 1, 1, 3))

#この時系列について、PredatorがResourceに与える間接効果を検証したい
#そこで、1.ResourceとPredatorの時系列のみを用いる方法、
#2.Resource埋め込み後にPredatorの時系列に置換する方法、
#3.全ての時系列を使う方法(fully multivariate)を比較

mlt_smap_res1 <- mvar_smap2(subset.g, 1, 3) #方法1

E <- simp_emb(subset.g[,1]) #方法2
E
## [1] 7
mlt_smap_res2 <- mvar_smapE(subset.g[, c(1, 3)], E)

mlt_smap_res3 <- mvar_smap3(subset.g, 1, 2, 3) #方法3


par(mfrow=c(4, 1), mar=c(3, 4, 1, 1), ps=18, lwd=1.5, family="sans")

plot(subset.g[, 1], type="l", ylim=c(25, 50), ylab="Abundance", xlab="Time", xaxt="n", lty=3)
lines(subset.g[, 3], ylim=c(10, 60), col="red", lty=3)
lines(pred ~ time, mlt_smap_res1$model_output[[1]], lwd=1, col=4)
lines(pred ~ time, mlt_smap_res2$model_output[[1]], lwd=1, col=5)
lines(pred ~ time, mlt_smap_res3$model_output[[1]], lwd=1, col=6)
axis(1, labels=c(200, 220, 240, 260, 280, 300), at=c(0, 20, 40, 60, 80, 100))
legend("bottomleft", 
       legend=c("Resource", "Predator", "Predict 1", "Predict 2", "Predict 3"), 
       col=c(1, 2, 4, 5, 6), lty=c(3, 3, 1, 1, 1))

plot(mlt_smap_res1$smap_coefficients[[1]]$c_2, type="l", ylim=c(-1, 1), 
     ylab="Predator -> Resource", xlab="Time", xaxt="n")
axis(1, labels=c(200, 220, 240, 260, 280, 300), at=c(0, 20, 40, 60, 80, 100))
abline(h=0, lty=2)
legend("topleft", legend=c("Predict 1"), bty="n")

plot(mlt_smap_res2$smap_coefficients[[1]]$c_2, type="l", ylim=c(-1, 1), 
     ylab="Predator -> Resource", xlab="Time", xaxt="n")
axis(1, labels=c(200, 220, 240, 260, 280, 300), at=c(0, 20, 40, 60, 80, 100))
abline(h=0, lty=2)
legend("topleft", legend=c("Predict 2"), bty="n")

plot(mlt_smap_res3$smap_coefficients[[1]]$c_3, type="l", ylim=c(-1, 1), 
     ylab="Predator -> Resource", xlab="Time", xaxt="n")
axis(1, labels=c(200, 220, 240, 260, 280, 300), at=c(0, 20, 40, 60, 80, 100))
abline(h=0, lty=2)
legend("topleft", legend=c("Predict 3"), bty="n")

dev.off()
## null device 
##           1

時系列100個によるシミュレーション

set.seed(1)
check.par <- NULL
for (i in 1:100){
  subset.g <- test.ts(1)[201:300, ]
  mlt_smap_res1 <- mvar_smap2(subset.g, 1, 3)
  rho_obs <- mlt_smap_res1$rho
  rmse_obs <- mlt_smap_res1$rmse
  IS_obs <- mean(mlt_smap_res1$smap_coefficients[[1]]$c_2, na.rm=TRUE)
  par_obs <- mean(mlt_smap_res1$smap_coefficients[[1]]$c_2*(1+bP*aP*lag(subset.g[,2])-cP)/
                    (subset.g[,1]*lag(subset.g[,2])), na.rm=TRUE)
  check.par <- rbind(check.par, data.frame(rho_obs, rmse_obs, IS_obs, par_obs))
}
check.par_2 <- check.par 

set.seed(1)
check.par <- NULL
for (i in 1:100){
  subset.g <- test.ts(1)[201:300, ]
  Ex <- simp_emb(subset.g)
  if(Ex<3){
  } else {
    mlt_smap_res1 <- mvar_smapE(subset.g[, c(1, 3)], Ex)
    rho_obs <- mlt_smap_res1$rho
    rmse_obs <- mlt_smap_res1$rmse
    IS_obs <- mean(mlt_smap_res1$smap_coefficients[[1]]$c_2, na.rm=TRUE)
    par_obs <- mean(mlt_smap_res1$smap_coefficients[[1]]$c_2*(1+bP*aP*lag(subset.g[,2])-cP)/
                      (subset.g[,1]*lag(subset.g[,2])), na.rm=TRUE)
    check.par <- rbind(check.par, data.frame(rho_obs, rmse_obs, IS_obs, par_obs))
  }
}
check.par_E <- check.par 

set.seed(1)
check.par <- NULL
for (i in 1:100){
  subset.g <- test.ts(1)[201:300, ]
  mlt_smap_res1 <- mvar_smap3(subset.g, 1, 2, 3)
  rho_obs <- mlt_smap_res1$rho
  rmse_obs <- mlt_smap_res1$rmse
  IS_obs <- mean(mlt_smap_res1$smap_coefficients[[1]]$c_3, na.rm=TRUE)
  par_obs <- mean(mlt_smap_res1$smap_coefficients[[1]]$c_3*(1+bP*aP*lag(subset.g[,2])-cP)/
                    (subset.g[,1]*lag(subset.g[,2])), na.rm=TRUE)
  check.par <- rbind(check.par, data.frame(rho_obs, rmse_obs, IS_obs, par_obs))
}
check.par_full <- check.par 


check.par <- rbind(check.par_2, check.par_E, check.par_full)
check.par$method <- as.factor(c(rep("2", times=nrow(check.par_2)), 
                                rep("E", times=nrow(check.par_E)), 
                                rep("Fully", times=nrow(check.par_full))))

par(mfrow=c(1, 4), ps=15, family="sans", lwd=1.5)
plot(rho_obs~method, check.par, ylab="rho")
plot(rmse_obs~method, check.par, ylab="RMSE")
plot(IS_obs~method, check.par, ylab="S-map coef (Predator -> Resource)")
abline(h=0, lty=3)
plot(par_obs~method, check.par, ylab="aC x aP (?)")
abline(h=0.0002, lty=3)