diff --git a/vignettes/camtrapr5.html b/vignettes/camtrapr5.html index d9a5aa3..104c3ab 100644 --- a/vignettes/camtrapr5.html +++ b/vignettes/camtrapr5.html @@ -8,1294 +8,37 @@ + - - - - -
library(camtrapR)
-library(purrr)
-library(DT)
-library(knitr)
-library(ggplot2)
-library(sf)
+Multi-species occupancy models are a powerful tool for combining @@ -4157,53 +3087,61 @@
First load the camera trap table and create a camera operation matrix:
- data("camtraps")
-
- camop_no_problem <- cameraOperation(CTtable = camtraps,
- stationCol = "Station",
- setupCol = "Setup_date",
- retrievalCol = "Retrieval_date",
- hasProblems = FALSE,
- dateFormat = "dmy"
- )
+First, we load the record table and create a list of detection histories. While all species are included in this example, you may choose to subset the record table beforehand. It is important to note the includeEffort = TRUE argument, which means that the output for each species will be a list containing both the detection history and effort matrix.
- data("recordTableSample")
-
- # list of detection histories
- DetHist_list <- lapply(unique(recordTableSample$Species), FUN = function(x) {
- detectionHistory(
- recordTable = recordTableSample,
- camOp = camop_no_problem,
- stationCol = "Station",
- speciesCol = "Species",
- recordDateTimeCol = "DateTimeOriginal",
- species = x, # this gets modifies by lapply
- occasionLength = 7,
- day1 = "station",
- datesAsOccasionNames = FALSE,
- includeEffort = TRUE,
- scaleEffort = FALSE,
- timeZone = "Asia/Kuala_Lumpur"
- )}
- )
-
- # assign species names to the list items
- names(DetHist_list) <- unique(recordTableSample$Species)
-
- # note, DetHist_list is a list containing a list for each species
+ data("recordTableSample")
+
+ # list of detection histories
+ DetHist_list <- lapply(unique(recordTableSample$Species), FUN = function(x) {
+ detectionHistory(
+ recordTable = recordTableSample,
+ camOp = camop_no_problem,
+ stationCol = "Station",
+ speciesCol = "Species",
+ recordDateTimeCol = "DateTimeOriginal",
+ species = x, # this gets modifies by lapply
+ occasionLength = 7,
+ day1 = "station",
+ datesAsOccasionNames = FALSE,
+ includeEffort = TRUE,
+ scaleEffort = FALSE,
+ timeZone = "Asia/Kuala_Lumpur"
+ )}
+ )
+
+ # assign species names to the list items
+ names(DetHist_list) <- unique(recordTableSample$Species)
+
+ # note, DetHist_list is a list containing a list for each species
Get the detection history of each species and put into a new list (thereby removing the effort matrix).
- ylist <- lapply(DetHist_list, FUN = function(x) x$detection_history)
+
Create some made-up covariates (only for demonstration):
- sitecovs <- camtraps[, c(1:3)]
- sitecovs$elevation <- c(300, 500, 600)
- sitecovs[, c(2:4)] <- scale(sitecovs[,-1]) # scale numeric covariates
- sitecovs$fact <- factor(c("A", "A", "B")) # categorical covariate
+Now we bundle the necessary data for communityModel
in a
list with 3 items:
data_list <- list(ylist = ylist,
- siteCovs = sitecovs,
- obsCovs = list(effort = DetHist_list[[1]]$effort)) # is identical for all species
+Now data_list
is a list containing the detection
histories, site covariates and occasion level covariates.
Please note that it is always necessary to provide an effort matrix. @@ -4238,15 +3178,17 @@
# text file to save the model
- modelfile1 <- tempfile(fileext = ".txt")
-
- mod.jags <- communityModel(data_list,
- occuCovs = list(fixed = "utm_y", ranef = "elevation"),
- detCovsObservation = list(fixed = "effort"),
- intercepts = list(det = "ranef", occu = "ranef"),
- modelFile = modelfile1)
-## Wrote model to C:\Users\NIEDBA~1\AppData\Local\Temp\Rtmpqkffp1\file1fb862774ec.txt
+## Wrote model to C:\Users\NIEDBA~1\AppData\Local\Temp\Rtmp4UNIvN\file4c5879e733bc.txt
This call defined a model with a fixed effect of utm_y on occupancy probability of all species, and a species-specific (random) effect of elevation on occupancy probability. Furthermore, we specified effort as @@ -4259,7 +3201,9 @@
One can also see the model code using (not shown here for brevity):
There is a very basic summary method for commOccu objects:
- summary(mod.jags)
+
## commOccu object for community occupancy model (in JAGS)
##
## 5 species, 3 stations, 7 occasions
@@ -4275,54 +3219,70 @@ Fit model in JAGS
## Available site-occasion covariates:
## effort
The model is fit with fit()
.
fit.jags <- fit(mod.jags,
- n.iter = 5000,
- n.burnin = 2500,
- chains = 3)
+
The output of the fit()
method is an
mcmc.list
from the coda package.
Summarize posterior estimates:
-fit_summary <- summary(fit.jags)
+
Statistics of parameter estimates:
-# Note, colors may not render correctly in dark themes in RStudio.
-DT::datatable(round(fit_summary$statistics, 3))
-
-
+Quantiles of parameter estimates:
-DT::datatable(round(fit_summary$quantiles, 3))
-
-
+
+
+
Marginal effect plots (response curves) can be plotted with
plot_effects()
. Argument submodel
defines
whether the output is for the detection or occupancy part of the
model:
plot_effects(mod.jags,
- fit.jags,
- submodel = "state")
+
## $utm_y
-
+
##
## $elevation
-
- plot_effects(mod.jags,
- fit.jags,
- submodel = "det")
+
+
## $effort
-
+
Likewise, we can plot effect sizes for easier comparison between
species and for easily checking significance with
plot_coef()
:
plot_coef(mod.jags,
- fit.jags,
- submodel = "state",
- combine = T)
+
## 'combine' and 'ordered' can't both be TRUE. Setting 'ordered = FALSE'
-
- plot_coef(mod.jags,
- fit.jags,
- submodel = "det")
+
+
## $effort
-
+
There are further arguments for the significance levels, sorting species by parameter estimates, and for combining multiple plots.
Using Nimble for community occupancy models requires the packages “nimble” and “nimbleEcology”:
-library(nimble)
-library(nimbleEcology)
+
Sys.getenv("PATH")
+
We can fit the same model in Nimble using the exact same functions as
for the JAGS model above. Only set nimble = TRUE
.
modelfile2 <- tempfile(fileext = ".txt")
-
- mod.nimble <- communityModel(data_list,
- occuCovs = list(fixed = "utm_x", ranef = "utm_y"),
- detCovsObservation = list(fixed = "effort"),
- intercepts = list(det = "ranef", occu = "ranef"),
- modelFile = modelfile2,
- nimble = TRUE) # set nimble = TRUE
-## Wrote model to C:\Users\NIEDBA~1\AppData\Local\Temp\Rtmpqkffp1\file1fb87f3c1ab3.txt
+## Wrote model to C:\Users\NIEDBA~1\AppData\Local\Temp\Rtmp4UNIvN\file4c5826ec4cd4.txt
It is possible to fit uncompiled models, but it is usually extremely slow and should only be done for checking model structure and expected outputs, using very few iterations.
- fit.nimble.uncomp <- fit(mod.nimble,
- n.iter = 10,
- chains = 1)
-
-# the notes and the error message above are harmless
+To fit a compiled model, set compile = TRUE:
- fit.nimble.comp <- fit(mod.nimble,
- n.iter = 20000,
- n.burnin = 10000,
- chains = 3,
- compile = TRUE,
-)
+The output as an mcmc.list
, just like for the JAGS model
above, and can be worked with just the same:
# parameter summary statistics (not shown)
- summary(fit.nimble.comp)
+
Response curves (= marginal effect plots):
- plot_effects(object = mod.nimble,
- mcmc.list = fit.nimble.comp,
- submodel = "state")
+
## $utm_x
-
+
##
## $utm_y
-
- plot_effects(object = mod.nimble,
- mcmc.list = fit.nimble.comp,
- submodel = "det")
+
+
## $effort
-
+
Effect size plots:
- plot_coef(mod.nimble,
- fit.nimble.comp,
- submodel = "state",
- combine = TRUE)
+
## 'combine' and 'ordered' can't both be TRUE. Setting 'ordered = FALSE'
-
- plot_coef(mod.nimble,
- fit.nimble.comp,
- submodel = "det")
+
+
## $effort
-
+
Traceplots (not shown)
- plot(fit.nimble.comp)
+
The estimates and marginal effects are not very pretty, and the model likely requires more iterations to achieve smooth estimates.
First, install the AHMbook package if necessary:
-install.packages("AHMbook")
-library(AHMbook)
+
+
Simulate community with simComm()
. Here we simulate a
community with 20 species, 30 camera trap stations and 5 occasions.
set.seed(10)
-com <- simComm(nspecies = 20,
- nsites = 30,
- nreps = 5,
- mean.psi = 0.25, # community mean of psi over all species in community (probability scale) (0.25 = -1.1 on logit scale)
- sig.lpsi = 1, # SD around intercept of logit(psi)
- mean.p = 0.25, # community mean of detection probability over all species (0.25 = -1.1 on logit scale)
- sig.lp = 1, # SD around intercept of logit(p)
- mu.beta.lpsi = 0.5, # mean (community) effect of habitat on logit(psi)
- sig.beta.lpsi = 0.5, # SD around mean (community) effect of habitat on logit(psi)
- mu.beta.lp = -0.5, # mean (community) effect of wind on logit(p)
- sig.beta.lp = 1) # SD around mean (community) effect of wind on logit(p)
-
+set.seed(10)
+com <- simComm(nspecies = 20,
+ nsites = 30,
+ nreps = 5,
+ mean.psi = 0.25, # community mean of psi over all species in community (probability scale) (0.25 = -1.1 on logit scale)
+ sig.lpsi = 1, # SD around intercept of logit(psi)
+ mean.p = 0.25, # community mean of detection probability over all species (0.25 = -1.1 on logit scale)
+ sig.lp = 1, # SD around intercept of logit(p)
+ mu.beta.lpsi = 0.5, # mean (community) effect of habitat on logit(psi)
+ sig.beta.lpsi = 0.5, # SD around mean (community) effect of habitat on logit(psi)
+ mu.beta.lp = -0.5, # mean (community) effect of wind on logit(p)
+ sig.beta.lp = 1) # SD around mean (community) effect of wind on logit(p)
## Warning: Plotting of output failed
+## the plotting window is too small.
+## Try calling 'dev.new()' before the 'sim*' function.
We need to wrangle the data a little to convert the data to input for
communityModel()
. This is only needed here because the data
are generated by AHMbook::simComm()
.
# get continuous site covariate "habitat"
-habitat <- com$habitat
-
-# create (fake) categorical covariate (3 levels)
-# setting "medium" as reference level
-categ <- factor(ifelse(habitat < -0.5, "low", ifelse(habitat < 0.5, "medium", "high")), levels = c("medium", "low", "high"))
-
-# get observation covariate
-wind <- com$wind
-
-# list of detection histories
-ylist <- purrr::array_branch(com$y.all, 3)
-
-# remove unobserved species (we leave that to data augmentation)
-ylist <- ylist[sapply(ylist, sum) >= 1]
-
-# here, effort was constant at all stations and occasions. Effort is thus a matrix of all 1
-effort <- matrix(1, nrow = nrow(ylist[[1]]), ncol = ncol(ylist[[1]]))
-
-# bundle data
-input_AHM <- list(ylist = ylist,
- siteCovs = data.frame(habitat = habitat,
- categ = categ),
- obsCovs = list(effort = effort,
- wind = wind))
+# get continuous site covariate "habitat"
+habitat <- com$habitat
+
+# create (fake) categorical covariate (3 levels)
+# setting "medium" as reference level
+categ <- factor(ifelse(habitat < -0.5, "low", ifelse(habitat < 0.5, "medium", "high")), levels = c("medium", "low", "high"))
+
+# get observation covariate
+wind <- com$wind
+
+# list of detection histories
+ylist <- purrr::array_branch(com$y.all, 3)
+
+# remove unobserved species (we leave that to data augmentation)
+ylist <- ylist[sapply(ylist, sum) >= 1]
+
+# here, effort was constant at all stations and occasions. Effort is thus a matrix of all 1
+effort <- matrix(1, nrow = nrow(ylist[[1]]), ncol = ncol(ylist[[1]]))
+
+# bundle data
+input_AHM <- list(ylist = ylist,
+ siteCovs = data.frame(habitat = habitat,
+ categ = categ),
+ obsCovs = list(effort = effort,
+ wind = wind))
Here’s a model in JAGS, with a species-specific effect of habitat on occupancy and wind on detection, and species-specific intercepts.
-modelFile_jags <- tempfile(fileext = ".txt")
-
-model1_jags <- communityModel(
- occuCovs = list(ranef = c("habitat")),
- detCovsObservation = list(ranef = "wind"),
- intercepts = list(det = "ranef", occu = "ranef"),
- data_list = input_AHM,
- modelFile = modelFile_jags)
+## Site covariates may not be scaled. Scaling is strongly recommended for numeric covariates.
-## Wrote model to C:\Users\NIEDBA~1\AppData\Local\Temp\Rtmpqkffp1\file1fb821176852.txt
-out_ahm_jags <- fit(model1_jags,
- n.iter = 10000,
- n.burnin = 5000,
- thin = 5,
- chains = 3,
- quiet = T
-)
+## Wrote model to C:\Users\NIEDBA~1\AppData\Local\Temp\Rtmp4UNIvN\file4c5822331a9c.txt
+Summary statistics of model parameters:
-DT::datatable(round(summary(out_ahm_jags)$statistics, 3))
-
-
+
+
+
Since we used simulated data we can compare model estimates with the
truth. For example, the true effect of habitat on occupancy was mean =
0.5 (SD = 0.5). See beta.ranef.cont.habitat.mean
and
@@ -4518,65 +3517,79 @@
Plot response curves (marginal effects)
-plot_resp_jags_occu <- plot_effects(model1_jags,
- out_ahm_jags)
-plot_resp_jags_occu
+
## $habitat
-
-plot_resp_jags_det <- plot_effects(model1_jags,
- out_ahm_jags,
- submodel = "det")
-plot_resp_jags_det
+
+## $wind
-
+
Plot coefficient estimates:
-plot_eff_jags_occu <- plot_coef(model1_jags,
- out_ahm_jags)
-plot_eff_jags_occu
+
## $habitat
-
-plot_eff_jags_det <- plot_coef(model1_jags,
- out_ahm_jags,
- submodel = "det")
-plot_eff_jags_det
+
+## $wind
-
+
By default, species are sorted by effect size. Alternatively, you can
have them sorted by species names. Set ordered = FALSE
:
plot_eff_jags_occu2 <- plot_coef(model1_jags,
- out_ahm_jags,
- ordered = FALSE)
-plot_eff_jags_occu2
+## $habitat
-
+
Here’s the same model in Nimble:
-modelFile_nimble <- tempfile(fileext = ".txt")
-
-model1_nimble <- communityModel(
- occuCovs = list(ranef = c("habitat")),
- detCovsObservation = list(ranef = "wind"),
- intercepts = list(det = "ranef", occu = "ranef"),
- data_list = input_AHM,
- modelFile = modelFile_nimble,
- nimble = TRUE)
+## Site covariates may not be scaled. Scaling is strongly recommended for numeric covariates.
-## Wrote model to C:\Users\NIEDBA~1\AppData\Local\Temp\Rtmpqkffp1\file1fb860083fb2.txt
+## Wrote model to C:\Users\NIEDBA~1\AppData\Local\Temp\Rtmp4UNIvN\file4c5859875d92.txt
We use some more iterations, since these Nimble models tend to require more iterations than equivalent JAGS models to achieve good estimates (numbers are still too low for publication quality though).
-# compiled model run
-out_ahm_nimble2 <- fit(model1_nimble,
- n.iter =20000,
- n.burnin = 10000,
- thin = 5,
- chains = 3,
- compile = TRUE,
- quiet = T
-)
+## Defining model
## [Note] Using 'y' (given within 'constants') as data.
## Building model
@@ -4596,31 +3609,41 @@ ## running chain 1...
## running chain 2...
## running chain 3...
-DT::datatable(round(summary(out_ahm_nimble2)$statistics, 3))
+
Plot responses (marginal effects):
-plot_resp_nimble_occu <- plot_effects(model1_nimble,
- out_ahm_nimble2)
-plot_resp_nimble_occu
+## $habitat
-
-plot_resp_nimble_det <- plot_effects(model1_nimble,
- out_ahm_nimble2,
- submodel = "det")
-plot_resp_nimble_det
+
+## $wind
-
+
Plot coefficient estimates:
-plot_eff_nimble_occu <- plot_coef(model1_nimble,
- out_ahm_nimble2)
-plot_eff_nimble_occu
+
## $habitat
-
-plot_eff_nimble_det <- plot_coef(model1_nimble,
- out_ahm_nimble2,
- submodel = "det")
-plot_eff_nimble_det
+
+## $wind
-
+
# introduce a few missing values in detection history of all species
-index_na <- sample(1:length(ylist[[1]]), 10) #
-ylist_with_na <- lapply(ylist, FUN = function(x) {x[index_na] <- NA; x})
-
-
-# set the cells with NA in detection history to NA in effort too
-effort_with_na <- effort
-effort_with_na[index_na] <- NA
-
-# bundle model input
-input_AHM_with_NA <- list(ylist = ylist_with_na,
- siteCovs = data.frame(habitat = habitat,
- categ = categ),
- obsCovs = list(effort = effort_with_na,
- wind = wind))
+# introduce a few missing values in detection history of all species
+index_na <- sample(1:length(ylist[[1]]), 10) #
+ylist_with_na <- lapply(ylist, FUN = function(x) {x[index_na] <- NA; x})
+
+
+# set the cells with NA in detection history to NA in effort too
+effort_with_na <- effort
+effort_with_na[index_na] <- NA
+
+# bundle model input
+input_AHM_with_NA <- list(ylist = ylist_with_na,
+ siteCovs = data.frame(habitat = habitat,
+ categ = categ),
+ obsCovs = list(effort = effort_with_na,
+ wind = wind))
And fit models in JAGS and Nimble:
-modelFile_jags_na <- tempfile(fileext = ".txt")
-
-model1_jags_na <- communityModel(
- occuCovs = list(ranef = c("habitat")),
- detCovsObservation = list(ranef = "wind"),
- intercepts = list(det = "ranef", occu = "ranef"),
- data_list = input_AHM_with_NA,
- modelFile = modelFile_jags_na)
+## Site covariates may not be scaled. Scaling is strongly recommended for numeric covariates.
-## Wrote model to C:\Users\NIEDBA~1\AppData\Local\Temp\Rtmpqkffp1\file1fb843216970.txt
-out_ahm_jags_na <- fit(model1_jags_na,
- n.iter = 5000,
- n.burnin = 2500,
- thin = 5,
- chains = 3,
- quiet = T
-)
+## Wrote model to C:\Users\NIEDBA~1\AppData\Local\Temp\Rtmp4UNIvN\file4c5836a72214.txt
+Summary statistics of model parameters:
-DT::datatable(round(summary(out_ahm_jags_na)$statistics, 3))
-
-
+
+
+
As can be seen, the JAGS model handles NAs well and parameter estimates are very similar to the model without missing data above.
Nimble models can technically also be fit with NAs present, but there will be numerous warnings and residuals as well as Bayesian p-values cannot be computed.
-modelFile_nimble_na <- tempfile(fileext = ".txt")
-
-model1_nimble_na <- communityModel(
- occuCovs = list(ranef = c("habitat")),
- detCovsObservation = list(ranef = "wind"),
- intercepts = list(det = "ranef", occu = "ranef"),
- data_list = input_AHM_with_NA,
- modelFile = modelFile_nimble_na,
- nimble = T)
+modelFile_nimble_na <- tempfile(fileext = ".txt")
+
+model1_nimble_na <- communityModel(
+ occuCovs = list(ranef = c("habitat")),
+ detCovsObservation = list(ranef = "wind"),
+ intercepts = list(det = "ranef", occu = "ranef"),
+ data_list = input_AHM_with_NA,
+ modelFile = modelFile_nimble_na,
+ nimble = T)
## Site covariates may not be scaled. Scaling is strongly recommended for numeric covariates.
-## Wrote model to C:\Users\NIEDBA~1\AppData\Local\Temp\Rtmpqkffp1\file1fb838e4c60.txt
+## Wrote model to C:\Users\NIEDBA~1\AppData\Local\Temp\Rtmp4UNIvN\file4c582b2b1f46.txt
When fitting the model there will be numerous warnings about values of data nodes y[,,] and determinisitc nodes res[,], R2[] and R3 being NA (not shown here).
-out_ahm_nimble_na <- fit(model1_nimble_na,
- n.iter = 5000,
- n.burnin = 2500,
- thin = 5,
- chains = 3,
- quiet = T
-)
+## Defining model
## [Note] Using 'y' (given within 'constants') as data.
## Building model
@@ -4716,14 +3751,18 @@ ## running chain 3...
Parameter summaries cannot be computed and will return an error (not shown here).
-DT::datatable(round(summary(out_ahm_nimble2)$statistics, 3))
+
To alleviate this, it is necessary (for Nimble models) to convert NAs in the detection history to 0, e.g. with:
-# replace NAs with 0 in the ylist component of input_AHM (for all species at once)
-input_AHM_with_NA$ylist <- lapply(input_AHM_with_NA$ylist, FUN = function(x) {
- x[is.na(x)] <- 0
- x
-})
+After converting NAs to 0, Nimble models can be run without warnings and summaries can be calculated.
To prevent the additional 0s from affecting the estimation of @@ -4772,52 +3811,58 @@
We know there are 20 species in the simulated community example. We
can inform the model that the community is known to consist of 20
species via: augmentation = c(maxknown = 20)
:
modelFile_jags_aug1 <- tempfile(fileext = ".txt")
-
-model1_jags_aug1 <- communityModel(
- occuCovs = list(ranef = c("habitat")),
- detCovsObservation = list(ranef = "wind"),
- intercepts = list(det = "ranef", occu = "ranef"),
- data_list = input_AHM,
- augmentation = c(maxknown = 20),
- modelFile = modelFile_jags_aug1)
-
-# short model run for demonstration
-out_ahm_jags_aug1 <- fit(model1_jags_aug1,
- n.iter = 500,
- n.burnin = 250,
- thin = 5,
- chains = 3,
- quiet = T
-)
+modelFile_jags_aug1 <- tempfile(fileext = ".txt")
+
+model1_jags_aug1 <- communityModel(
+ occuCovs = list(ranef = c("habitat")),
+ detCovsObservation = list(ranef = "wind"),
+ intercepts = list(det = "ranef", occu = "ranef"),
+ data_list = input_AHM,
+ augmentation = c(maxknown = 20),
+ modelFile = modelFile_jags_aug1)
+
+# short model run for demonstration
+out_ahm_jags_aug1 <- fit(model1_jags_aug1,
+ n.iter = 500,
+ n.burnin = 250,
+ thin = 5,
+ chains = 3,
+ quiet = T
+)
Here is another example with fully open data augmentation
(metacommunity size is unknown). The model will estimate the probability
for each species to be part of the metacommunity. Fully open data
augmentation is specified with augmentation = c(full = 30)
(for a maximum potential community size of 30 species in this
example).
modelFile_jags_aug2 <- tempfile(fileext = ".txt")
-
-model1_jags_aug2 <- communityModel(
- occuCovs = list(ranef = c("habitat")),
- detCovsObservation = list(ranef = "wind"),
- intercepts = list(det = "ranef", occu = "ranef"),
- data_list = input_AHM,
- augmentation = c(full = 30),
- modelFile = modelFile_jags_aug2)
-
-# short model run for demonstration
-out_ahm_jags_aug2 <- fit(model1_jags_aug2,
- n.iter = 500,
- n.burnin = 250,
- thin = 5,
- chains = 3,
- quiet = T
-)
+modelFile_jags_aug2 <- tempfile(fileext = ".txt")
+
+model1_jags_aug2 <- communityModel(
+ occuCovs = list(ranef = c("habitat")),
+ detCovsObservation = list(ranef = "wind"),
+ intercepts = list(det = "ranef", occu = "ranef"),
+ data_list = input_AHM,
+ augmentation = c(full = 30),
+ modelFile = modelFile_jags_aug2)
+
+# short model run for demonstration
+out_ahm_jags_aug2 <- fit(model1_jags_aug2,
+ n.iter = 500,
+ n.burnin = 250,
+ thin = 5,
+ chains = 3,
+ quiet = T
+)
See parameters “omega” and “w[1]” to “w[30]” in the model output:
-DT::datatable(round(summary(out_ahm_jags_aug2)$statistics, 3))
-
-
+
+
+
Higher numbers of species in data augmentation increase model run time.
Here is an example with a categorical site covariate “categ” on occupancy:
-modelFile_jags_categ1 <- tempfile(fileext = ".txt")
-
-model_jags_categ1 <- communityModel(
- occuCovs = list(ranef = c("categ")),
- detCovsObservation = list(ranef = "wind"),
- intercepts = list(det = "ranef", occu = "ranef"),
- data_list = input_AHM,
- modelFile = modelFile_jags_categ1)
-
-# short model run for demonstration
-out_ahm_jags_categ1 <- fit(model_jags_categ1,
- n.iter = 500,
- n.burnin = 250,
- thin = 5,
- chains = 3,
- quiet = T
-)
+modelFile_jags_categ1 <- tempfile(fileext = ".txt")
+
+model_jags_categ1 <- communityModel(
+ occuCovs = list(ranef = c("categ")),
+ detCovsObservation = list(ranef = "wind"),
+ intercepts = list(det = "ranef", occu = "ranef"),
+ data_list = input_AHM,
+ modelFile = modelFile_jags_categ1)
+
+# short model run for demonstration
+out_ahm_jags_categ1 <- fit(model_jags_categ1,
+ n.iter = 500,
+ n.burnin = 250,
+ thin = 5,
+ chains = 3,
+ quiet = T
+)
Plot the results:
-plot_effects(object = model_jags_categ1,
- mcmc.list = out_ahm_jags_categ1)
+
## $categ
-
-plot_coef(object = model_jags_categ1,
- mcmc.list = out_ahm_jags_categ1)
+
+
## $categ
-
+
In the table below, see the arguments
beta.ranef.categ.categ
. The species effects have two
indices: [species, factorLevel]. Accordingly, there are three estimates
@@ -4866,9 +3917,11 @@
DT::datatable(round(summary(out_ahm_jags_categ1)$statistics, 3))
-
-
+
+
+
# Create example categorical observation covariate
-input_AHM$obsCovs$wind_categ <- ifelse(input_AHM$obsCovs$wind > 0, "windy", "calm")
-
-# result is a character matrix:
-str(input_AHM$obsCovs$wind_categ)
+## chr [1:30, 1:5] "calm" "calm" "windy" "windy" "calm" "calm" "windy" "calm" "calm" "calm" "windy" "calm" "calm" "windy" "calm" "calm" "windy" "calm" "calm" ...
Model example:
-modelFile_jags_categ2 <- tempfile(fileext = ".txt")
-
-model_jags_categ2 <- communityModel(
- occuCovs = list(fixed = c("habitat")),
- detCovsObservation = list(ranef = c("wind_categ")), # "wind_categ" now
- intercepts = list(det = "ranef", occu = "ranef"),
- data_list = input_AHM,
- modelFile = modelFile_jags_categ2)
-
-out_ahm_jags_categ2 <- fit(model_jags_categ2,
- n.iter = 500,
- n.burnin = 250,
- thin = 5,
- chains = 3,
- quiet = T,
- compile = FALSE
-)
+modelFile_jags_categ2 <- tempfile(fileext = ".txt")
+
+model_jags_categ2 <- communityModel(
+ occuCovs = list(fixed = c("habitat")),
+ detCovsObservation = list(ranef = c("wind_categ")), # "wind_categ" now
+ intercepts = list(det = "ranef", occu = "ranef"),
+ data_list = input_AHM,
+ modelFile = modelFile_jags_categ2)
+
+out_ahm_jags_categ2 <- fit(model_jags_categ2,
+ n.iter = 500,
+ n.burnin = 250,
+ thin = 5,
+ chains = 3,
+ quiet = T,
+ compile = FALSE
+)
Model estimates. As above, the estimates for the first factor level
are 0. The relevant parameters here are called
alpha.obs.ranef.categ.wind_categ
.
DT::datatable(round(summary(out_ahm_jags_categ2)$statistics, 3))
-
-
+
+
+
Plot the results:
-plot_effects(object = model_jags_categ2,
- mcmc.list = out_ahm_jags_categ2,
- submodel = "det")
+## $wind_categ
-
-plot_coef(object = model_jags_categ2,
- mcmc.list = out_ahm_jags_categ2,
- submodel = "det")
+
+## $wind_categ
-
+
detCovs(ranef = c(“covariate1|covariate2”))
Here is an example, where the effect of “habitat” differs between levels of “categ”.
-modelFile_jags_ranef <- tempfile(fileext = ".txt")
-
-model1_jags_ranef <- communityModel(
- occuCovs = list(ranef = c("habitat|categ")),
- detCovsObservation = list(ranef = "wind"),
- intercepts = list(det = "ranef", occu = "ranef"),
- data_list = input_AHM,
- modelFile = modelFile_jags_ranef)
-
-# short model run for demonstration
-out_ahm_jags_ranef <- fit(model1_jags_ranef,
- n.iter = 500,
- n.burnin = 250,
- thin = 5,
- chains = 3,
- quiet = T
-)
+modelFile_jags_ranef <- tempfile(fileext = ".txt")
+
+model1_jags_ranef <- communityModel(
+ occuCovs = list(ranef = c("habitat|categ")),
+ detCovsObservation = list(ranef = "wind"),
+ intercepts = list(det = "ranef", occu = "ranef"),
+ data_list = input_AHM,
+ modelFile = modelFile_jags_ranef)
+
+# short model run for demonstration
+out_ahm_jags_ranef <- fit(model1_jags_ranef,
+ n.iter = 500,
+ n.burnin = 250,
+ thin = 5,
+ chains = 3,
+ quiet = T
+)
Search for the term “habitat_categ” in the table below. There are 2 estimates (for stations with “A” and “B”), plus the mean and sigma of the random effect (this is only for demonstration, 2 factor levels is of course not enough for applying random effects).
-DT::datatable(round(summary(out_ahm_jags_ranef)$statistics, 3))
-
-
+
+
+
Currently random effects other than species can not be plotted with
plot_effects
and plot_coef
.
occuCovs(ranef = c(“covariate1|covariate2+Species”))
Here is an example, with independent random effect of “categ” on “habitat” for each species:
-modelFile_jags_nested <- tempfile(fileext = ".txt")
-
-model1_jags_nested <- communityModel(
- occuCovs = list(ranef = c("habitat|categ+Species")),
- detCovsObservation = list(ranef = "wind"),
- intercepts = list(det = "ranef", occu = "ranef"),
- data_list = input_AHM,
- modelFile = modelFile_jags_nested)
-
-# short model run for demonstration
-out_ahm_jags_nested <- fit(model1_jags_nested,
- n.iter = 500,
- n.burnin = 250,
- thin = 5,
- chains = 3,
- quiet = T
-)
+modelFile_jags_nested <- tempfile(fileext = ".txt")
+
+model1_jags_nested <- communityModel(
+ occuCovs = list(ranef = c("habitat|categ+Species")),
+ detCovsObservation = list(ranef = "wind"),
+ intercepts = list(det = "ranef", occu = "ranef"),
+ data_list = input_AHM,
+ modelFile = modelFile_jags_nested)
+
+# short model run for demonstration
+out_ahm_jags_nested <- fit(model1_jags_nested,
+ n.iter = 500,
+ n.burnin = 250,
+ thin = 5,
+ chains = 3,
+ quiet = T
+)
Search for the term “habitat_categ_Species” in the table below. Depending on the number of species and factor levels The number of parameter estimates is very high when using nested random effects.
-DT::datatable(round(summary(out_ahm_jags_nested)$statistics, 3))
-
-
+
+
+
Currently nested random effects can not be plotted with
plot_effects
and plot_coef
.
Site is defined as the sampling location (e.g. camera trap station in this context).
Below is an example model:
-modelFile_jags_species_station_ran <- tempfile(fileext = ".txt")
-
-model1_jags_species_station_ran <- communityModel(
- occuCovs = list(ranef = c("habitat")),
- detCovsObservation = list(ranef = "wind"),
- intercepts = list(det = "ranef", occu = "ranef"),
- speciesSiteRandomEffect = list(det = TRUE),
- data_list = input_AHM,
- modelFile = modelFile_jags_species_station_ran)
-
-# short model run for demonstration
-out_ahm_jags_species_station_ran <- fit(model1_jags_species_station_ran,
- n.iter = 500,
- n.burnin = 250,
- thin = 5,
- chains = 3,
- quiet = T
-)
+modelFile_jags_species_station_ran <- tempfile(fileext = ".txt")
+
+model1_jags_species_station_ran <- communityModel(
+ occuCovs = list(ranef = c("habitat")),
+ detCovsObservation = list(ranef = "wind"),
+ intercepts = list(det = "ranef", occu = "ranef"),
+ speciesSiteRandomEffect = list(det = TRUE),
+ data_list = input_AHM,
+ modelFile = modelFile_jags_species_station_ran)
+
+# short model run for demonstration
+out_ahm_jags_species_station_ran <- fit(model1_jags_species_station_ran,
+ n.iter = 500,
+ n.burnin = 250,
+ thin = 5,
+ chains = 3,
+ quiet = T
+)
The model returns the standard deviation of this random effect as
alpha.speciessite.ranef.sigma
, which can be found in the
table below.
DT::datatable(round(summary(out_ahm_jags_species_station_ran)$statistics, 3))
-
-
+
+
+
Covariates should be scaled to prior to squaring (“habitat” in this examples is already scaled).
Create quadratic covariate:
-input_AHM$siteCovs$habitat_squared <- input_AHM$siteCovs$habitat ^2
+
Create and fit model:
-modelFile_jags_quadratic <- tempfile(fileext = ".txt")
-
-
-model1_jags_quadratic <- communityModel(
- occuCovs = list(ranef = c("habitat", "habitat_squared")),
- detCovsObservation = list(ranef = "wind"),
- intercepts = list(det = "ranef", occu = "ranef"),
- data_list = input_AHM,
- modelFile = modelFile_jags_quadratic,
- keyword_quadratic = "_squared") # this is the default, added for clarity
-
-# short model run for demonstration
-out_ahm_jags_quadratic<- fit(model1_jags_quadratic,
- n.iter = 10000,
- n.burnin = 5000,
- thin = 5,
- chains = 3,
- quiet = T
-)
+modelFile_jags_quadratic <- tempfile(fileext = ".txt")
+
+
+model1_jags_quadratic <- communityModel(
+ occuCovs = list(ranef = c("habitat", "habitat_squared")),
+ detCovsObservation = list(ranef = "wind"),
+ intercepts = list(det = "ranef", occu = "ranef"),
+ data_list = input_AHM,
+ modelFile = modelFile_jags_quadratic,
+ keyword_quadratic = "_squared") # this is the default, added for clarity
+
+# short model run for demonstration
+out_ahm_jags_quadratic<- fit(model1_jags_quadratic,
+ n.iter = 10000,
+ n.burnin = 5000,
+ thin = 5,
+ chains = 3,
+ quiet = T
+)
Thanks to to keyword “_squared” in the covariate name,
plot_effects
knows that “habitat” and “habitat_squared” are
the same covariate and will combine the effects of “habitat” and
“habitat_squared” in response curves. If a different keyword was used,
set the parameter “keyword_quadratic” accordingly (it defaults to
“_squared”).
plot_effects(model1_jags_quadratic,
- out_ahm_jags_quadratic)
+
## $habitat
-
+
The simulated data have no quadratic relationship with covariates, hence the quadratic effects are rather weak in this example.
Nimble models can return WAIC. Set argument
fit(..., WAIC = TRUE)
.
out_ahm_nimble3 <- fit(model1_nimble,
- n.iter = 500,
- n.burnin = 250,
- thin = 5,
- chains = 3,
- compile = TRUE,
- quiet = F,
- WAIC = TRUE
-)
+The message about “individual pWAIC values that are greater than 0.4” in the example is likely due to the short model run.
If WAIC = TRUE
, the output will be a list with 2
elements. The first (“samples”) is the familiar mcmc.list, the second
(“WAIC”) is a waicList.
mcmc.list is accessible with $samples:
-# not printed here
-summary(out_ahm_nimble3$samples)$statistics
+
WAIC:
-out_ahm_nimble3$WAIC
+
## nimbleList object of type waicNimbleList
## Field "WAIC":
## [1] 1071.5
@@ -5125,36 +4212,40 @@ Richness estimates for categorical covariates
can be used to calculate separate species richness estimates for
different levels of categorical site covariates. If it is not defined,
there will only be global and by-station species richness estimates.
-modelFile_jags_richness <- tempfile(fileext = ".txt")
-
-model1_jags_richness <- communityModel(
- occuCovs = list(ranef = c("habitat")),
- detCovsObservation = list(ranef = "wind"),
- intercepts = list(det = "ranef", occu = "ranef"),
- data_list = input_AHM,
- richnessCategories = "categ",
- modelFile = modelFile_jags_richness)
-
-# short model run for demonstration
-out_ahm_jags_rich <- fit(model1_jags_richness,
- n.iter = 500,
- n.burnin = 250,
- thin = 5,
- chains = 3,
- quiet = T
-)
+Code
+modelFile_jags_richness <- tempfile(fileext = ".txt")
+
+model1_jags_richness <- communityModel(
+ occuCovs = list(ranef = c("habitat")),
+ detCovsObservation = list(ranef = "wind"),
+ intercepts = list(det = "ranef", occu = "ranef"),
+ data_list = input_AHM,
+ richnessCategories = "categ",
+ modelFile = modelFile_jags_richness)
+
+# short model run for demonstration
+out_ahm_jags_rich <- fit(model1_jags_richness,
+ n.iter = 500,
+ n.burnin = 250,
+ thin = 5,
+ chains = 3,
+ quiet = T
+)
+
Now search for “Nspecies” in the table below. You will see entries
for three different parameters.
- “Nspecies” is overall species richness,
- “Nspecies_by_category[1]”, “…[2]” and “…[3]” are for the stations in
-category “medium” and “low”, “high” respectively.
+category “medium”, “low”, and “high” respectively.
- “Nspecies_by_station[1]” to “…[30]” are species richness estimates
for each sampling station.
-DT::datatable(round(summary(out_ahm_jags_rich)$statistics, 3))
-
-
+
+
+
@@ -5163,72 +4254,94 @@ Spatial predictions
created with communityModel
, their model fits and covariate
rasters.
This requires the terra package.
- library(terra)
+
For demonstration we will use a model that has both a continuous and
a categorical covariate.
-modelFile_jags_categ3 <- tempfile(fileext = ".txt")
-
-model_jags_categ3 <- communityModel(
- occuCovs = list(ranef = c("habitat",
- "categ")),
- detCovsObservation = list(ranef = "wind"),
- intercepts = list(det = "ranef", occu = "ranef"),
- data_list = input_AHM,
- modelFile = modelFile_jags_categ3)
-
-# short model run for demonstration
-out_ahm_jags_categ3 <- fit(model_jags_categ3,
- n.iter = 500,
- n.burnin = 250,
- thin = 5,
- chains = 3,
- quiet = T
-)
+Code
+modelFile_jags_categ3 <- tempfile(fileext = ".txt")
+
+model_jags_categ3 <- communityModel(
+ occuCovs = list(ranef = c("habitat",
+ "categ")),
+ detCovsObservation = list(ranef = "wind"),
+ intercepts = list(det = "ranef", occu = "ranef"),
+ data_list = input_AHM,
+ modelFile = modelFile_jags_categ3)
+
+# short model run for demonstration
+out_ahm_jags_categ3 <- fit(model_jags_categ3,
+ n.iter = 500,
+ n.burnin = 250,
+ thin = 5,
+ chains = 3,
+ quiet = T
+)
+
Create a habitat raster. We’ll use the volcano
raster for demonstration. The coordinates are not geographic though
since this is only for demonstration.
-data("volcano")
-r_volcano <- scale(rast(volcano))
+
Create a categorical raster. Since it is not
possible to have categorical raster (with data type “factor”), the
raster must consist of integer numbers that refer to the factor levels
(as defined in the model input).
-levels(input_AHM$siteCovs$categ) # show the order of factor levels, first one is reference
+
## [1] "medium" "low" "high"
-raster_categ <- rast(x = matrix(rep(c(1,2, 3), each = ncell(r_volcano) / 3),
- ncol = ncol(r_volcano),
- nrow = nrow(r_volcano)))
-# add raster to list
-stack_prediction <- rast(list(habitat = r_volcano,
- categ = raster_categ))
-
-plot(stack_prediction, asp = 1)
-
-# raster categ, from west to east: 1 = medium, 2 = low, 3 = high
+Code
+
+
+Code
+
+
+
+
Species occupancy maps:
-# species occupancy estimates
- predictions_psi <- predict(object = model_jags_categ3,
- mcmc.list = out_ahm_jags_categ3,
- x = stack_prediction,
- type = "psi",
- draws = 1000)
+Code
+
+
## draws (1000) is greater than the number of available samples (150).
- plot(predictions_psi$mean, zlim = c(0,1),
- col = hcl.colors(100),
- maxnl = 9, # plotting only the first 9 species for space reasons
- asp = 1)
-
+Code
+
+
+
Species richness maps:
-# species richness estimates
- predictions_rich <- predict(object = model_jags_categ3,
- mcmc.list = out_ahm_jags_categ3,
- x = stack_prediction,
- type = "richness")
-
- plot(predictions_rich, col = hcl.colors(100), asp = 1)
-
- # mean = mean species richness estimate
- # sd = standard deviation of richness estimate
+Code
+
+
+
+
In these examples we did not return confidence intervals. Doing so
would be easy by setting intervals = "confidence"
.
Computation can take long on larger rasters and can require lots of
@@ -5243,74 +4356,94 @@
Percentage of area occupied (by species)
For demonstration, let’s create a AOI as a simple feature (from the
sf package) Normally you’d just load a shapefile or other spatial vector
data set.
-Sr1 = st_polygon(list(cbind(c(10, 10, 30, 30, 10),
- c(40, 70, 80, 40, 40))))
-aoi <- data.frame(name = "My AOI")
-st_geometry(aoi) <- st_geometry(Sr1)
-plot(r_volcano)
-plot(vect(aoi), add = T) # easier plotting via SpatVect object from terra
-
+Code
+
+
+
+
To use the vector layer as an AOI, we need to rasterize it. PAO will
refer to all cells in the AOI raster that are not NA.
-r_aoi <- rasterize(aoi, r_volcano)
-plot(r_aoi)
-
+
+
Now the prediction of PAO:
- predictions_pao <- predict(object = model_jags_categ3,
- mcmc.list = out_ahm_jags_categ3,
- x = stack_prediction,
- type = "pao",
- aoi = r_aoi)
+Code
+
+
## No id variables; using all as measure variables
## No id variables; using all as measure variables
Output is a list with several components:
$pao_summary is a summary table with quantiles of predicted PAO for
all species.
-predictions_pao$pao_summary
+
## Min. lower.ci.0.025 1st Qu. Median Mean 3rd Qu. upper.ci.0.975 Max.
-## sp1 0.017 0.038 0.183 0.371 0.393 0.607 0.819 0.941
-## sp2 0.014 0.047 0.181 0.359 0.372 0.538 0.765 0.846
-## sp3 0.027 0.062 0.178 0.297 0.350 0.510 0.821 0.883
-## sp4 0.226 0.321 0.655 0.771 0.735 0.862 0.936 0.966
-## sp5 0.040 0.065 0.176 0.301 0.376 0.561 0.887 0.907
-## sp6 0.240 0.385 0.760 0.879 0.821 0.923 0.969 0.979
-## sp7 0.046 0.105 0.326 0.551 0.522 0.721 0.881 0.903
-## sp8 0.014 0.023 0.089 0.175 0.207 0.286 0.566 0.660
-## sp9 0.019 0.103 0.290 0.506 0.479 0.657 0.849 0.913
-## sp10 0.019 0.033 0.088 0.161 0.228 0.354 0.605 0.744
-## sp11 0.146 0.189 0.569 0.744 0.673 0.825 0.889 0.919
-## sp12 0.071 0.151 0.476 0.644 0.597 0.754 0.892 0.913
-## sp13 0.010 0.020 0.087 0.184 0.229 0.319 0.701 0.850
-## sp14 0.116 0.190 0.471 0.660 0.623 0.786 0.915 0.940
-## sp15 0.030 0.060 0.227 0.450 0.432 0.619 0.835 0.889
-## sp16 0.070 0.128 0.306 0.488 0.484 0.671 0.800 0.893
-## sp18 0.010 0.040 0.188 0.386 0.384 0.565 0.801 0.867
-## sp19 0.026 0.058 0.243 0.461 0.434 0.597 0.829 0.859
-## sp20 0.014 0.088 0.285 0.479 0.462 0.617 0.835 0.923
+## sp1 0.031 0.050 0.130 0.229 0.296 0.430 0.745 0.820
+## sp2 0.007 0.028 0.104 0.267 0.297 0.440 0.734 0.814
+## sp3 0.007 0.030 0.120 0.232 0.309 0.490 0.775 0.886
+## sp4 0.084 0.151 0.617 0.761 0.697 0.865 0.928 0.956
+## sp5 0.041 0.056 0.132 0.223 0.284 0.400 0.765 0.833
+## sp6 0.247 0.332 0.691 0.850 0.779 0.911 0.968 0.990
+## sp7 0.017 0.056 0.228 0.408 0.440 0.659 0.871 0.933
+## sp8 0.016 0.033 0.072 0.114 0.166 0.219 0.484 0.657
+## sp9 0.030 0.062 0.243 0.383 0.407 0.580 0.820 0.857
+## sp10 0.014 0.024 0.076 0.136 0.175 0.198 0.605 0.736
+## sp11 0.040 0.141 0.555 0.739 0.663 0.814 0.911 0.936
+## sp12 0.051 0.108 0.387 0.603 0.569 0.767 0.928 0.937
+## sp13 0.003 0.015 0.068 0.134 0.200 0.299 0.665 0.701
+## sp14 0.074 0.141 0.399 0.613 0.586 0.789 0.912 0.961
+## sp15 0.024 0.047 0.179 0.335 0.371 0.557 0.835 0.870
+## sp16 0.049 0.111 0.289 0.526 0.493 0.702 0.820 0.846
+## sp18 0.027 0.039 0.172 0.387 0.402 0.619 0.821 0.899
+## sp19 0.003 0.032 0.139 0.307 0.363 0.560 0.839 0.869
+## sp20 0.006 0.028 0.216 0.446 0.447 0.667 0.873 0.909
$pao_matrix contains the PAO estimates for all species from all
posterior draws (not shown here)
-predictions_pao$pao_matrix
+
$pao_df is similar to $pao_matrix, but in a data frame in long
format, ready for use in ggplot2.
- ggplot2::ggplot(predictions_pao$pao_df, aes(x = Species , y = PAO)) +
- geom_boxplot(outlier.shape = NA) +
- theme(axis.text.x = element_text(angle = 45, hjust = 1))
-
+Code
+
+
+
$aoi is a raster layer (SpatRaster) showing the AOI (now with cells
removed that are NA in the prediction rasters)
-plot(predictions_pao$aoi)
-
+
+
bayesplot
We can also use the powerful bayesplot package for visualizing model
estimates. One downside is that it won’t automatically insert the
species names.
-library(bayesplot)
+
Here is an example for density plots showing the species-level
effects of habitat on occupancy:
-mcmc_areas(out_ahm_nimble2, regex_pars = "beta.ranef.cont.habitat")
-
+
+
bayesplot has many other visualization options beyond this example.
See the respective documentation, e.g. https://mc-stan.org/bayesplot/.
@@ -5319,12 +4452,16 @@ Model diagnostics
Output of fit()
is a coda::mcmc.list, so
plot()
provides traceplots (not shown here for space
reasons):
-plot(out_ahm_nimble2)
+
The Gelman-Rubin convergence statistic (potential scale reduction
factor) can be calculated with gelman.diag()
from
coda
:
-gd <- coda::gelman.diag(out_ahm_nimble2, multivariate = FALSE)
-gd
+
## Potential scale reduction factors:
##
## Point est. Upper C.I.
@@ -5415,8 +4552,10 @@ Model diagnostics
One can also use gelman.plot
to create
Gelman-Rubin-Brooks plots (evolution of Gelman-Rubin statistic over
iterations):
-# not shown here due to space reasons
-coda::gelman.plot(out_ahm_nimble2, multivariate = FALSE)
+Code
+
+
Royle-Nichols model
@@ -5427,104 +4566,130 @@ Royle-Nichols model
is a derived parameter: the probability that at least one individual is
available for detection at the site. It is achieve by setting the
parameter “model” to “RN”:
-modelFile_jags_RN <- tempfile(fileext = ".txt")
-
-model1_jags_RN <- communityModel(
- model = "RN",
- occuCovs = list(ranef = c("habitat")),
- detCovsObservation = list(ranef = "wind"),
- intercepts = list(det = "ranef", occu = "ranef"),
- data_list = input_AHM,
- modelFile = modelFile_jags_RN)
+Code
+
+
## Site covariates may not be scaled. Scaling is strongly recommended for numeric covariates.
-## Wrote model to C:\Users\NIEDBA~1\AppData\Local\Temp\Rtmpqkffp1\file1fb846ea4aff.txt
-out_ahm_jags_RN <- fit(model1_jags_RN,
- n.iter = 5000,
- n.burnin = 2500,
- thin = 5,
- chains = 3,
- quiet = T
-)
+## Wrote model to C:\Users\NIEDBA~1\AppData\Local\Temp\Rtmp4UNIvN\file4c5845247c3f.txt
+Code
+
+
The models can be processed as shown before, e.g.:
Summary statistics of model parameters:
-DT::datatable(round(summary(out_ahm_jags_RN)$statistics, 3))
-
-
+
+
+
Response curves (marginal effect plots).
-# In the occupancy (state) submodel, one can show abundance (the latent quantity modelled)
-plot_effects(model1_jags_RN,
- out_ahm_jags_RN,
- submodel = "state",
- response = "abundance")
+Code
+
+
## $habitat
-
-# In the occupancy (state) submodel, one can also show occupancy (which is derived from abundance):
-plot_effects(model1_jags_RN,
- out_ahm_jags_RN,
- submodel = "state",
- response = "occupancy")
+
+Code
+
+
## $habitat
-
-plot_effects(model1_jags_RN,
- out_ahm_jags_RN,
- submodel = "det")
+
+
## $wind
-
+
Coefficient plots:
-plot_coef(model1_jags_RN,
- out_ahm_jags_RN,
- ordered = FALSE)
+
## $habitat
-
-plot_coef(model1_jags_RN,
- out_ahm_jags_RN,
- ordered = FALSE,
- submodel = "det")
+
+
## $wind
-
+
Predictions work as before, but a Royle-Nichols model allows for
returning expected species abundance (lambda) via type = “abundance” and
type = “lambda_array”. Occupancy predictions internally convert
abundance to occupancy.
Occupancy predictions (type = “psi”)
-predictions_psi_RN <- predict(object = model1_jags_RN,
- mcmc.list = out_ahm_jags_RN,
- x = stack_prediction,
- type = "psi",
- draws = 200)
-plot(predictions_psi_RN$mean,
- col = hcl.colors(100),
- maxnl = 9) # first 9 species only
-
+Code
+
+
+
Abundance predictions (type = “abundance”):
-predictions_abundance_RN <- predict(object = model1_jags_RN,
- mcmc.list = out_ahm_jags_RN,
- x = stack_prediction,
- type = "abundance",
- draws = 200)
-plot(predictions_abundance_RN$mean,
- col = hcl.colors(100),
- maxnl = 9) # first 9 species only
-
+Code
+
+
+
Richness predictions (type = “richness”)
- predictions_richness_RN <- predict(object = model1_jags_RN,
- mcmc.list = out_ahm_jags_RN,
- x = stack_prediction,
- type = "richness",
- draws = 200)
-plot(predictions_richness_RN$mean, col = hcl.colors(100))
-
+Code
+
+
+
PAO predictions (type = “pao”):
- predictions_pao_RN <- predict(object = model1_jags_RN,
- mcmc.list = out_ahm_jags_RN,
- x = stack_prediction,
- type = "pao",
- draws = 200)
+Code
+
+
## No id variables; using all as measure variables
## No id variables; using all as measure variables
-DT::datatable(predictions_pao_RN$pao_summary)
-
-
+
+
+
Single-species occupancy models
@@ -5541,24 +4706,32 @@ Single-species occupancy models
covariates as in the example below.
In this example we use species 1 from the community created with
AHMbook::simComm
.
-input_AHM_sp1 <- list(ylist = ylist[1], # ylist[1] is still a list, with 1 element
- siteCovs = input_AHM$siteCovs,
- obsCovs = input_AHM$obsCovs)
+Code
+
+
Create model:
-modelFile_jags_sp1 <- tempfile(fileext = ".txt")
-
-model_sp1_jags_ranef <- communityModel(
- occuCovs = list(ranef = c("habitat|categ")), # response to habitat differs between categ via random effect
- detCovsObservation = list(fixed = "wind"),
- intercepts = list(det = "fixed", occu = "fixed"),
- data_list = input_AHM_sp1,
- modelFile = modelFile_jags_sp1)
+Code
+modelFile_jags_sp1 <- tempfile(fileext = ".txt")
+
+model_sp1_jags_ranef <- communityModel(
+ occuCovs = list(ranef = c("habitat|categ")), # response to habitat differs between categ via random effect
+ detCovsObservation = list(fixed = "wind"),
+ intercepts = list(det = "fixed", occu = "fixed"),
+ data_list = input_AHM_sp1,
+ modelFile = modelFile_jags_sp1)
+
Fit model:
-fit_jags_sp1 <- fit(model_sp1_jags_ranef, n.iter = 1000, n.burnin = 500, thin = 5)
+
Print summary statistics:
-DT::datatable(round(summary(fit_jags_sp1)$statistics, 3))
-
-
+
+
+
The plot_effects()
and plot_coef()
functions currently don’t work for this case, since single-species
models are mostly a side-effect of the intended community occupancy
@@ -5570,69 +4743,8 @@
Single-species occupancy models
-
-
-
-
-
-
-
-
-
-
-
-