context("occuTTD fitting function")
skip_on_cran()
test_that("unmarkedFrameOccuTTD can be constructed",{
set.seed(123)
N <- 100
psi <- 0.4
lam <- 7
Tmax <- 10
z <- rbinom(N, 1, psi)
y <- rexp(N, 1/lam)
y[z==0] <- Tmax
y[y>Tmax] <- Tmax
sc <- as.data.frame(matrix(rnorm(N*2),ncol=2))
oc <- as.data.frame(matrix(rnorm(N*2),ncol=2))
umf <- unmarkedFrameOccuTTD(y=y, surveyLength=Tmax, siteCovs=sc, obsCovs=oc)
expect_equivalent(getY(umf), y)
expect_equivalent(dim(getY(umf)), c(100,1))
expect_equivalent(siteCovs(umf), sc)
expect_equivalent(obsCovs(umf), oc)
expect_equivalent(umf@numPrimary, 1)
expect_equivalent(umf@surveyLength, matrix(Tmax, 100, 1))
expect_is(umf, "unmarkedFrameOccuTTD")
out <- capture.output(umf)
expect_equal(out[1], "Data frame representation of unmarkedFrame object.")
s <- capture.output(summary(umf))
expect_equal(s[3], "100 sites")
hd <- head(umf)
expect_equivalent(as(hd, 'data.frame'), as(umf, 'data.frame')[1:10,])
umf_sub <- umf[c(1,3),]
expect_equivalent(as(umf_sub, 'data.frame'), as(umf, 'data.frame')[c(1,3),])
expect_error(umf[,2])
sl_bad <- c(10,10)
expect_error(unmarkedFrameOccuTTD(y, sl_bad))
# plot
pdf(NULL)
pl <- plot(umf)
expect_is(pl, "histogram")
dev.off()
## Multiple observers
y <- cbind(y,y)
oc <- as.data.frame(matrix(rnorm(N*2*2),ncol=2))
tm <- cbind(rep(10,N),rep(5,N))
umf <- unmarkedFrameOccuTTD(y=y, surveyLength=tm, siteCovs=sc, obsCovs=oc)
expect_equivalent(getY(umf), y)
expect_equivalent(dim(getY(umf)), c(100,2))
expect_equivalent(obsCovs(umf), oc)
expect_equivalent(umf@numPrimary, 1)
expect_equivalent(umf@surveyLength, tm)
expect_error(umf[,2])
## Multiple primary periods
umf <- unmarkedFrameOccuTTD(y=y, surveyLength=tm, siteCovs=sc,
yearlySiteCovs=oc, numPrimary=2)
expect_equivalent(yearlySiteCovs(umf), oc)
expect_equivalent(umf@numPrimary, 2)
umf_sub <- umf[,2]
expect_equivalent(getY(umf_sub), y[,2,drop=F])
y <- rexp(N, 1/lam)
y <- cbind(y,y,y)
expect_error(unmarkedFrameOccuTTD(y,Tmax,numPrimary=2))
})
test_that("occuTTD R and C engines return same results",{
skip_on_cran()
set.seed(123)
N <- 20; J <- 1
#Simulate occupancy
scovs <- data.frame(elev=c(scale(runif(N, 0,100))),
forest=runif(N,0,1),
wind=runif(N,0,1))
beta_N <- c(-0.69, 0.71, -0.5)
lambda_N <- exp(cbind(1, scovs$elev, scovs$forest) %*% beta_N)
abun <- rpois(N, lambda_N)
z <- as.numeric(abun>0)
#Simulate detection
Tmax <- 10
beta_lam <- c(-2, -0.2, 0.7)
rate <- exp(cbind(1, scovs$elev, scovs$wind) %*% beta_lam)
ttd <- rexp(N, rate)
ttd[z==0] <- Tmax
ttd[ttd>Tmax] <- Tmax
#Build UMF
umf <- unmarkedFrameOccuTTD(y=ttd, surveyLength=Tmax, siteCovs=scovs)
fitR <- occuTTD(psiformula=~elev, detformula=~wind,
data=umf, linkPsi='cloglog', ttdDist='exp',engine="R")
fitC <- occuTTD(psiformula=~elev, detformula=~wind,
data=umf, linkPsi='cloglog', ttdDist='exp',engine="C")
expect_equal(coef(fitR), coef(fitC), tol=1e-5)
})
test_that("occuTTD can fit a single-season 1 obs model",{
#One observer------------------------------------
set.seed(123)
N <- 500; J <- 1
#Simulate occupancy
scovs <- data.frame(elev=c(scale(runif(N, 0,100))),
forest=runif(N,0,1),
wind=runif(N,0,1))
beta_N <- c(-0.69, 0.71, -0.5)
lambda_N <- exp(cbind(1, scovs$elev, scovs$forest) %*% beta_N)
abun <- rpois(N, lambda_N)
z <- as.numeric(abun>0)
#Simulate detection
Tmax <- 10
beta_lam <- c(-2, -0.2, 0.7)
rate <- exp(cbind(1, scovs$elev, scovs$wind) %*% beta_lam)
ttd <- rexp(N, rate)
ttd[z==0] <- Tmax
ttd[ttd>Tmax] <- Tmax
#Build UMF
umf <- unmarkedFrameOccuTTD(y=ttd, surveyLength=Tmax, siteCovs=scovs)
#fitR <- occuTTD(psiformula=~elev+forest, detformula=~elev+wind,
# data=umf, linkPsi='cloglog', ttdDist='exp',engine="R")
fitC <- occuTTD(psiformula=~elev+forest, detformula=~elev+wind,
data=umf, linkPsi='cloglog', ttdDist='exp',engine="C")
#expect_equivalent(coef(fitR), coef(fitC), tol=1e-5)
expect_equivalent(coef(fitC), c(-0.6271,0.8157,-0.5982,-2.0588,
-0.4042,1.2328), tol=1e-4)
expect_equivalent(coef(fitC), c(beta_N, beta_lam), tol=0.3)
#Check weibull
#fitR <- occuTTD(psiformula=~elev+forest, detformula=~elev+wind,
# data=umf, linkPsi='cloglog',
# ttdDist='weibull',engine="R")
fitC <- occuTTD(psiformula=~elev+forest, detformula=~elev+wind,
data=umf, linkPsi='cloglog', ttdDist='weibull',
engine="C")
#expect_equivalent(coef(fitR), coef(fitC))
expect_equivalent(coef(fitC), c(-0.6846,0.7807,-0.5662,-1.9600,
-0.3779,1.1474,0.06856), tol=1e-4)
#Check missing value handling
ttd_na <- ttd; ttd_na[1] <- NA
umf_na <- unmarkedFrameOccuTTD(y=ttd_na, Tmax, siteCovs=scovs)
#fit_naR <- occuTTD(psiformula=~elev+forest, detformula=~elev+wind,
# data=umf_na, linkPsi='cloglog',
# ttdDist='weibull',engine="R")
expect_warning(fit_naC <- occuTTD(psiformula=~elev+forest, detformula=~elev+wind,
data=umf_na, linkPsi='cloglog', ttdDist='weibull',
engine="C"))
#expect_equivalent(coef(fit_naR), coef(fit_naC), tol=1e-5)
expect_equivalent(fit_naC@AIC, 1185.15, tol=1e-4)
expect_equivalent(fit_naC@sitesRemoved, 1)
set.seed(123)
p <- parboot(fitC, nsim=3)
expect_equivalent(p@t.star[1,], 87.90704)
r <- ranef(fitC)
expect_equivalent(dim(r@post), c(N,2,1))
b <- bup(r)
expect_equivalent(length(b), N)
})
test_that("occuTTD can fit a single-season multi-obs model",{
set.seed(123)
N <- 500
beta_N <- c(-0.69, 0.71, -0.5)
beta_lam <- c(-2, -0.2, 0.7)
scovs <- data.frame(elev=c(scale(runif(N, 0,100))),
forest=runif(N,0,1),
wind=runif(N,0,1))
lambda_N <- exp(cbind(1, scovs$elev, scovs$forest) %*% beta_N)
abun <- rpois(N, lambda_N)
z <- as.numeric(abun>0)
ocovs <- data.frame(obs=rep(c('A','B'),N))
Tmax <- 10
rate <- exp(cbind(1, scovs$elev, scovs$wind) %*% beta_lam)
rateB <- exp(cbind(1, scovs$elev, scovs$wind) %*% beta_lam + 0.2)
rate2 <- as.numeric(t(cbind(rate, rateB)))
set.seed(123)
ttd <- rexp(N*2, rate2)
ttd[ttd>Tmax] <- Tmax
ttd <- matrix(ttd, nrow=N, byrow=T)
ttd[z==0,] <- Tmax
expect_warning(umf <- unmarkedFrameOccuTTD(y=ttd, surveyLength=Tmax,
siteCovs=scovs, obsCovs=ocovs))
#fitR <- occuTTD(psiformula=~elev+forest, detformula=~elev+wind+obs,
# data=umf, linkPsi='cloglog', ttdDist='exp',engine="R")
fitC <- occuTTD(psiformula=~elev+forest, detformula=~elev+wind+obs,
data=umf, linkPsi='cloglog', ttdDist='exp',engine="C")
#expect_equivalent(coef(fitR), coef(fitC))
#Check predict
expect_equivalent(as.numeric(predict(fitC, 'psi')[4,]),
c(0.7562,0.0407,0.6385,0.8588), tol=1e-4)
expect_equivalent(as.numeric(predict(fitC, 'det')[1,]),
c(0.16059,0.02349,0.12056,0.2139), tol=1e-4)
expect_error(predict(fitC, 'col'))
#Check getP
gp <- getP(fitC)
expect_equivalent(dim(gp), c(500,2))
expect_equivalent(gp[1,], c(0.79929,0.8679),tol=1e-4)
#Check fitted
ft <- fitted(fitC)
expect_equivalent(dim(ft),c(500,2))
expect_equivalent(ft[1,], c(0.17963,0.19505), tol=1e-4)
#Check residuals
r <- residuals(fitC)
expect_equivalent(dim(r),c(500,2))
expect_equivalent(r[1,], c(0.82036,0.80494), tol=1e-4)
#Check ranef
r <- ranef(fitC)
expect_equivalent(dim(r@post), c(N,2,1))
b <- bup(r)
expect_equivalent(length(b), N)
#Check site is retained when only one observation is missing
ttd_na <- ttd; ttd_na[1,1] <- NA
expect_warning(umf_na <- unmarkedFrameOccuTTD(y=ttd_na, Tmax, siteCovs=scovs,
obsCovs=ocovs))
#fit_naR <- occuTTD(psiformula=~elev+forest, detformula=~elev+wind+obs,
# data=umf_na, linkPsi='cloglog',
# ttdDist='weibull',engine="R")
fit_naC <- occuTTD(psiformula=~elev+forest, detformula=~elev+wind+obs,
data=umf_na, linkPsi='cloglog', ttdDist='weibull',
engine="C")
#expect_equivalent(coef(fit_naR), coef(fit_naC), tol=1e-5)
expect_equivalent(fit_naC@sitesRemoved, numeric(0))
#Check site is removed when both obs are NA
ttd_na <- ttd; ttd_na[1,] <- NA
expect_warning(umf_na <- unmarkedFrameOccuTTD(y=ttd_na, Tmax, siteCovs=scovs,
obsCovs=ocovs))
expect_warning(fit_naC <- occuTTD(psiformula=~elev+forest, detformula=~elev+wind+obs,
data=umf_na, linkPsi='cloglog',
ttdDist='weibull',engine="C"))
expect_equivalent(fit_naC@sitesRemoved, 1)
#Check logit link
set.seed(123)
#Simulate occupancy
scovs <- data.frame(elev=c(scale(runif(N, 0,100))),
forest=runif(N,0,1),
wind=runif(N,0,1))
beta_N <- c(-0.69, 0.71, -0.5)
psi <- plogis(cbind(1, scovs$elev, scovs$forest) %*% beta_N)
z <- rbinom(N, 1, psi)
#Simulate detection
Tmax <- 10
beta_lam <- c(-2, -0.2, 0.7)
rate <- exp(cbind(1, scovs$elev, scovs$wind) %*% beta_lam)
ttd <- rexp(N, rate)
ttd[z==0] <- Tmax
ttd[ttd>Tmax] <- Tmax
umf <- unmarkedFrameOccuTTD(y=ttd, surveyLength=Tmax, siteCovs=scovs)
#fitR <- occuTTD(psiformula=~elev+forest, detformula=~elev+wind,
# data=umf, linkPsi='logit', ttdDist='exp',engine="R")
fitC <- occuTTD(psiformula=~elev+forest, detformula=~elev+wind,
data=umf, linkPsi='logit', ttdDist='exp',engine="C")
#expect_equivalent(coef(fitR), coef(fitC))
expect_equivalent(coef(fitC), c(-0.5102,0.67941,-0.88612,-2.1219,
-0.41504,1.3224), tol=1e-4)
# Check error when random effect in formula
expect_error(occuTTD(~(1|dummy), ~1, data=umf))
})
test_that("occuTTD can fit a dynamic model",{
set.seed(123)
#Simulate initial occupancy
N <- 1000; J <- 1; T <- 2
scovs <- data.frame(elev=c(scale(runif(N, 0,100))),
forest=runif(N,0,1),
wind=runif(N,0,1))
beta_psi <- c(-0.69, 0.71, -0.5)
psi <- plogis(cbind(1, scovs$elev, scovs$forest) %*% beta_psi)
z <- matrix(NA, N, T)
z[,1] <- rbinom(N, 1, psi)
#Col/ext process
ysc <- data.frame(forest=rep(scovs$forest, each=T),
elev=rep(scovs$elev, each=T))
c_b0 <- -0.4; c_b1 <- 0.3
gam <- plogis(c_b0 + c_b1 * scovs$forest)
e_b0 <- -0.7; e_b1 <- 0.4
ext <- plogis(e_b0 + e_b1 * scovs$elev)
for (i in 1:N){
for (t in 1:(T-1)){
if(z[i,t]==1){
#ext
z[i,t+1] <- rbinom(1, 1, (1-ext[i]))
} else {
#col
z[i,t+1] <- rbinom(1,1, gam[i])
}
}
}
#Simulate detection
ocovs <- data.frame(obs=rep(c('A','B'),N*T))
Tmax <- 10
beta_lam <- c(-2, -0.2, 0.7)
rate <- exp(cbind(1, scovs$elev, scovs$wind) %*% beta_lam)
rateB <- exp(cbind(1, scovs$elev, scovs$wind) %*% beta_lam - 0.5)
#Across seasons
rate2 <- as.numeric(t(cbind(rate, rateB, rate, rateB)))
ttd <- rexp(N*T*2, rate2)
ttd <- matrix(ttd, nrow=N, byrow=T)
ttd[ttd>Tmax] <- Tmax
ttd[z[,1]==0,1:2] <- Tmax
ttd[z[,2]==0,3:4] <- Tmax
expect_warning(umf <- unmarkedFrameOccuTTD(y = ttd, surveyLength = Tmax,
siteCovs = scovs, obsCovs=ocovs,
yearlySiteCovs=ysc, numPrimary=2))
fit <- occuTTD(psiformula=~elev+forest,detformula=~elev+wind+obs,
gammaformula=~forest, epsilonformula=~elev,
data=umf,se=T,
linkPsi='logit',ttdDist='exp',engine="C")
truth <- c(beta_psi, c_b0, c_b1, e_b0, e_b1, beta_lam, -0.5)
#expect_equivalent(coef(fit), truth, tol=0.1)
expect_equivalent(fit@AIC, 9354.081,tol=1e-4)
umf_new <- umf[1:100,]
fit <- occuTTD(psiformula=~elev+forest,detformula=~elev+wind+obs,
gammaformula=~forest, epsilonformula=~elev,
data=umf_new,se=T,
linkPsi='logit',ttdDist='exp',engine="C")
s <- simulate(fit, nsim=2)
expect_equivalent(length(s),2)
expect_equivalent(dim(s[[1]]), c(100,4))
r <- residuals(fit)
expect_equivalent(dim(r), c(100,4))
pdf(NULL)
plotEffects(fit, 'psi', 'elev')
plotEffects(fit, 'col', 'forest')
plotEffects(fit, 'det', 'wind')
plotEffects(fit, 'det', 'obs')
dev.off()
#Check ranef
r <- ranef(fit)
expect_equivalent(dim(r@post), c(100,2,T))
b <- bup(r)
expect_equivalent(dim(b), c(100,T))
# Check T > 2 works
N <- 100; J <- 1; T <- 3
scovs <- data.frame(elev=c(scale(runif(N, 0,100))),
forest=runif(N,0,1),
wind=runif(N,0,1))
beta_psi <- c(-0.69, 0.71, -0.5)
psi <- plogis(cbind(1, scovs$elev, scovs$forest) %*% beta_psi)
z <- matrix(NA, N, T)
z[,1] <- rbinom(N, 1, psi)
#Col/ext process
ysc <- data.frame(forest=rep(scovs$forest, each=T),
elev=rep(scovs$elev, each=T))
c_b0 <- -0.4; c_b1 <- 0.3
gam <- plogis(c_b0 + c_b1 * scovs$forest)
e_b0 <- -0.7; e_b1 <- 0.4
ext <- plogis(e_b0 + e_b1 * scovs$elev)
for (i in 1:N){
for (t in 1:(T-1)){
if(z[i,t]==1){
#ext
z[i,t+1] <- rbinom(1, 1, (1-ext[i]))
} else {
#col
z[i,t+1] <- rbinom(1,1, gam[i])
}
}
}
#Simulate detection
ocovs <- data.frame(obs=rep(c('A','B'),N*T))
Tmax <- 10
beta_lam <- c(-2, -0.2, 0.7)
rate <- exp(cbind(1, scovs$elev, scovs$wind) %*% beta_lam)
rateB <- exp(cbind(1, scovs$elev, scovs$wind) %*% beta_lam - 0.5)
#Across seasons
rate2 <- as.numeric(t(cbind(rate, rateB, rate, rateB)))
ttd <- rexp(N*T*2, rate2)
ttd <- matrix(ttd, nrow=N, byrow=T)
ttd[ttd>Tmax] <- Tmax
ttd[z[,1]==0,1:2] <- Tmax
ttd[z[,2]==0,3:4] <- Tmax
expect_warning(umf <- unmarkedFrameOccuTTD(y = ttd, surveyLength = Tmax,
siteCovs = scovs, obsCovs=ocovs,
yearlySiteCovs=ysc, numPrimary=T))
fit2 <- occuTTD(psiformula=~elev+forest,detformula=~elev+wind+obs,
gammaformula=~forest, epsilonformula=~elev,
data=umf,se=T,
linkPsi='logit',ttdDist='exp',engine="C")
expect_is(fit2, "unmarkedFitOccuTTD")
})
test_that("occuMulti predict works",{
#One observer------------------------------------
set.seed(123)
N <- 500; J <- 1
#Simulate occupancy
scovs <- data.frame(elev=c(scale(runif(N, 0,100))),
forest=runif(N,0,1),
wind=runif(N,0,1))
beta_N <- c(-0.69, 0.71, -0.5)
lambda_N <- exp(cbind(1, scovs$elev, scovs$forest) %*% beta_N)
abun <- rpois(N, lambda_N)
z <- as.numeric(abun>0)
#Simulate detection
Tmax <- 10
beta_lam <- c(-2, -0.2, 0.7)
rate <- exp(cbind(1, scovs$elev, scovs$wind) %*% beta_lam)
ttd <- rexp(N, rate)
ttd[z==0] <- Tmax
ttd[ttd>Tmax] <- Tmax
#Build UMF
umf <- unmarkedFrameOccuTTD(y=ttd, surveyLength=Tmax, siteCovs=scovs)
fitC <- occuTTD(psiformula=~elev+scale(forest), detformula=~elev+wind,
data=umf, linkPsi='cloglog', ttdDist='exp',engine="C")
nd1 <- siteCovs(umf)[1:2,]
nd2 <- siteCovs(umf)[1:5,]
pr1 <- predict(fitC, 'psi', newdata=nd1)$Predicted
pr2 <- predict(fitC, 'psi', newdata=nd2)$Predicted[1:2]
expect_equivalent(pr1,pr2)
#Check factors
scovs$fac_cov <- factor(sample(c('a','b','c'), N, replace=T),
levels=c('b','a','c'))
umf <- unmarkedFrameOccuTTD(y=ttd, surveyLength=Tmax, siteCovs=scovs)
fitC <- occuTTD(psiformula=~fac_cov, detformula=~elev+wind,
data=umf, linkPsi='cloglog', ttdDist='exp',engine="C")
pr1 <- predict(fitC, 'psi', newdata=data.frame(fac_cov=c('b','a')))
pr2 <- predict(fitC, 'psi', newdata=data.frame(fac_cov=c('a','b')))
pr3 <- predict(fitC, 'psi', newdata=data.frame(fac_cov=factor(c('a','b'))))
expect_equivalent(as.matrix(pr1),as.matrix(pr2[2:1,]))
expect_equivalent(as.matrix(pr1),as.matrix(pr3[2:1,]))
expect_error(predict(fitC, 'psi', newdata=data.frame(fac_cov=c('a','d'))))
})
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.