Llanganates Spatial Factor Multi-Species Occupancy Model

Data from: Langanates

model
code
analysis
102 sites, 19 mammal species
Authors

German Forero

Robert Wallace

Galo Zapara-Rios

Emiliana Isasi-Catalá

Diego J. Lizcano

Published

August 16, 2025

Single-species occupancy models

Single-species occupancy models (MacKenzie et al., 2002) are widely used in ecology to estimate and predict the spatial distribution of a species from data collected in presence–absence repeated surveys. The popularity of these models stems from their ability to estimate the effects of environmental or management covariates on species occurrences, while accounting for false-negative errors in detection, which are common in surveys of natural populations.

Multi-species occupancy models

Multi-species occupancy models for estimating the effects of environmental covariates on several species occurrences while accounting for imperfect detection were build on the principle of the Single-species occupancy model, and developed more than 20 years ago.

Multi-species occupancy models are a powerful tool for combining information from multiple species to estimate both individual and community-level responses to management and environmental variables.

Objective

We want to asses the effect of protected areas on the occupancy of the species. We hypothesize that several mammal species have benefited of the conservation actions provided by protected areas, so we expect a decreases in occupancy from the interior of the protected area to the exterior as a function of the distance to the protected area border.

To account for several ecological factors we also tested and included elevation and forest integrity index as occupancy covariates.

We used the newly developed R package spOccupancy as approach to modelling the probability of occurrence of each species as a function of fixed effects of measured environmental covariates and random effects designed to account for unobserved sources of spatial dependence (spatial autocorrelation).

Code
library(grateful) # Facilitate Citation of R Packages
library(readxl) # Read Excel Files
library(DT) # A Wrapper of the JavaScript Library 'DataTables'
library(sf) # Simple Features for R
library(mapview) # Interactive Viewing of Spatial Data in R
library(maps) # Draw Geographical Maps
library(tmap) # Thematic Maps
library(terra) # Spatial Data Analysis
library(elevatr) # Access Elevation Data from Various APIs

# library(rjags) # Bayesian Graphical Models using MCMC 
library(bayesplot) # Plotting for Bayesian Models # Plotting for Bayesian Models
library(tictoc) # Functions for Timing R Scripts, as Well as Implementations of "Stack" and "StackList" Structures 
library(MCMCvis) # Tools to Visualize, Manipulate, and Summarize MCMC Output
library(coda) # Output Analysis and Diagnostics for MCMC
library(beepr) # Easily Play Notification Sounds on any Platform 
library(snowfall) # Easier Cluster Computing (Based on 'snow')

#library(ggmcmc)
library(camtrapR) # Camera Trap Data Management and Preparation 
library(spOccupancy) # Single-Species, Multi-Species, and Integrated Spatial Occupancy
library(tidyverse) # Easily Install and Load the 'Tidyverse'

Fitting a Multi-Species Spatial Occupancy Model

We use a more computationally efficient approach for fitting spatial multi-species occupancy models. This alternative approach is called a “spatial factor multi-species occupancy model”, and is described in depth in Doser, Finley, and Banerjee (2023). This newer approach also accounts for residual species correlations (i.e., it is a joint species distribution model with imperfect detection). The simulation results from Doser, Finley, and Banerjee (2023) show that this new alternative approach outperforms, or performs equally to spMsPGOcc(), while being substantially faster.

The Latent factor multi-species occupancy model is described in detail here

Data from Plantas Medicinales Putumayo

Here we use the table: - COL-18-Putumayo2023

Code
source("C:/CodigoR/WCS-CameraTrap/R/organiza_datos_v3.R")

AP_PlantasMed <- read_sf("C:/CodigoR/Occu_APs/shp/PlantasMedicinales/WDPA_WDOECM_May2025_Public_555511938_shp-polygons.shp")

### Ecu 17, Ecu 18, ECU 20, Ecu 22  

# load data and make array_locID column
Col_18 <- loadproject("F:/WCS-CameraTrap/data/BDcorregidas/Colombia/COL-018-Putumayo2023_WCS_WI.xlsx") |> mutate(array_locID=paste("Col_18", locationID, sep="_"))


# get sites
Col_18_sites <- get.sites("F:/WCS-CameraTrap/data/BDcorregidas/Colombia/COL-018-Putumayo2023_WCS_WI.xlsx")



# get elevation map
elevation_18 <- rast(get_elev_raster(Col_18_sites, z = 10)) #z =1-14
# bb <-  st_as_sfc(st_bbox(elevation_17)) # make bounding box 




# extract covs using points and add to _sites
covs_Col_18_sites <- cbind(Col_18_sites, terra::extract(elevation_18, Col_18_sites))
# covs_Col_17_sites <- cbind(Col_17_sites, terra::extract(elevation_17, Col_17_sites))


# get which are in and out
covs_Col_18_sites$in_AP = st_intersects(covs_Col_18_sites, AP_PlantasMed, sparse = FALSE)
# covs_Col_17_sites$in_AP = st_intersects(covs_Col_17_sites, AP_Yasuni, sparse = FALSE)




# make a map
mapview (elevation_18, alpha=0.5) + 
  mapview (AP_PlantasMed, color = "green", col.regions = "green", alpha = 0.5) +
  mapview (covs_Col_18_sites, zcol = "in_AP", col.regions =c("red","blue"), burst = TRUE) 
  # mapview (covs_Col_17_sites, zcol = "in_AP", col.regions =c("red","blue"), burst = TRUE) +

Data fom Bajo Madidi and Heath

Here we use the tables: - BOL-008a - BOL-008b - BOL14a - BOL14b

Code
source("C:/CodigoR/WCS-CameraTrap/R/organiza_datos_v3.R")

Area_Madidi <- read_sf("C:/CodigoR/Occu_APs/shp/Area_Madidi/WDPA_WDOECM_Jul2025_Public_303894_shp-polygons.shp")

Madidi_NP <- read_sf("C:/CodigoR/Occu_APs/shp/Madidi_NP/WDPA_WDOECM_Jul2025_Public_98183_shp-polygons.shp")
#AP_Tahuayo <- read_sf("C:/CodigoR/Occu_APs/shp/Tahuayo/WDPA_WDOECM_Jun2025_Public_555555621_shp-polygons.shp")

# load data and make array_locID column
#Bol_Pacaya <- read_excel("F:/WCS-CameraTrap/data/BDcorregidas/Peru/PER-003_BD_ACRCTT_T0.xlsx", sheet = "Image")


Bol_Madidi_1 <- loadproject("F:/WCS-CameraTrap/data/BDcorregidas/Bolivia/Guido/BOL-008a.xlsx") |> mutate(Point.x=as.character(paste("M1",Point.x, sep = "-"))) |> mutate(Point.y=as.character(paste("M1",Point.y, sep = "-")))

Bol_Madidi_2 <- loadproject("F:/WCS-CameraTrap/data/BDcorregidas/Bolivia/Guido/BOL-008b.xlsx") |> mutate(Point.x=as.character(paste("M2",Point.x, sep = "-"))) |> mutate(Point.y=as.character(paste("M2",Point.y, sep = "-")))

Bol_Madidi_3 <- loadproject("F:/WCS-CameraTrap/data/BDcorregidas/Bolivia/Guido/BOL-014a.xlsx")|> mutate(Point.x=as.character(paste("M3",Point.x, sep = "-"))) |> mutate(Point.y=as.character(paste("M3",Point.y, sep = "-")))

Bol_Madidi_4 <- loadproject("F:/WCS-CameraTrap/data/BDcorregidas/Bolivia/Guido/BOL-014b.xlsx")|> mutate(Point.x=as.character(paste("M4",Point.x, sep = "-"))) |> mutate(Point.y=as.character(paste("M1",Point.y, sep = "-")))


FLII2016 <- rast("C:/CodigoR/WCS_2024/FLI/raster/FLII_final/FLII_2016.tif")



# get sites
Bol_Madidi_sites1 <-  Bol_Madidi_1 |> 
   dplyr::bind_rows(Bol_Madidi_2) |> 
   dplyr::bind_rows(Bol_Madidi_3) |> 
   dplyr::bind_rows(Bol_Madidi_4) |> 
  select("Latitude", "Longitude", "Point.x" 
) |> dplyr::distinct( )  

Bol_Madidi_sites <- sf::st_as_sf(Bol_Madidi_sites1, coords = c("Longitude","Latitude"))
st_crs(Bol_Madidi_sites) <- 4326


# get elevation map
elevation_17 <- rast(get_elev_raster(Bol_Madidi_sites, z = 9)) #z =1-14
# bb <-  st_as_sfc(st_bbox(elevation_17)) # make bounding box 




# extract covs using points and add to _sites
covs_Bol_Madidi_sites <- cbind(Bol_Madidi_sites, terra::extract(elevation_17, Bol_Madidi_sites))
# covs_Ecu_17_sites <- cbind(Ecu_17_sites, terra::extract(elevation_17, Ecu_17_sites))


# get which are in and out
covs_Bol_Madidi_sites$in_AP = st_intersects(covs_Bol_Madidi_sites, Madidi_NP, sparse = FALSE)
# covs_Ecu_17_sites$in_AP = st_intersects(covs_Ecu_17_sites, AP_Machalilla, sparse = FALSE)


# make a map
mapview (elevation_17, alpha=0.7) + 
  mapview (Madidi_NP, color = "green", col.regions = "green", alpha = 0.5) +
  mapview (Area_Madidi, color = "yellow", col.regions = "yellow", alpha = 0.5) +
  #mapview (AP_Tahuayo, color = "green", col.regions = "green", alpha = 0.5) +
  mapview (covs_Bol_Madidi_sites, zcol = "in_AP", col.regions =c("red","blue"), burst = TRUE) 

Tamshiyacu Tahuayo data

Here we use the tables: - PER-003_BD_ACRCTT_T0.xlsx - PER-002_BD_ACRTT-PILOTO.xlsx

Code
source("C:/CodigoR/WCS-CameraTrap/R/organiza_datos_v3.R")

AP_Pacaya <- read_sf("C:/CodigoR/Occu_APs/shp/PacayaSamiria/WDPA_WDOECM_Jun2025_Public_249_shp-polygons.shp")

AP_Tahuayo <- read_sf("C:/CodigoR/Occu_APs/shp/Tahuayo/WDPA_WDOECM_Jun2025_Public_555555621_shp-polygons.shp")

# load data and make array_locID column
Per_Tahuayo_piloto <- loadproject("F:/WCS-CameraTrap/data/BDcorregidas/Peru/PER-002_BD_ACRTT-PILOTO.xlsx")



Per_Tahuayo <- loadproject("F:/WCS-CameraTrap/data/BDcorregidas/Peru/PER-003_BD_ACRCTT_T0.xlsx")

 
FLII2016 <- rast("C:/CodigoR/WCS_2024/FLI/raster/FLII_final/FLII_2016.tif")

# get sites
# Per_Pacaya_sites <- get.sites("F:/WCS-CameraTrap/data/BDcorregidas/Peru/PER-003_BD_ACRCTT_T0.xlsx")

# get sites
Per_Tahuayo_sites1 <- Per_Tahuayo |> select("Latitude",
                                    "Longitude",
                                    "Camera_Id" 
                                    ) |> dplyr::distinct( )  

Per_Tahuayo_sites <- sf::st_as_sf(Per_Tahuayo_sites1, coords = c("Longitude","Latitude"))
st_crs(Per_Tahuayo_sites) <- 4326



# get Pacaya sites
Per_Tahuayo_piloto_sites1 <- Per_Tahuayo_piloto |> select("Latitude",
                                    "Longitude",
                                    "Camera_Id" 
                                    ) |> dplyr::distinct( )  

Per_Tahuayo_piloto_sites <- sf::st_as_sf(Per_Tahuayo_piloto_sites1, coords = c("Longitude","Latitude"))
st_crs(Per_Tahuayo_piloto_sites) <- 4326




# get elevation map
elevation_PE <- rast(get_elev_raster(Per_Tahuayo_sites, z = 10)) #z =1-14
# bb <-  st_as_sfc(st_bbox(elevation_17)) # make bounding box 





# extract covs using points and add to _sites
covs_Per_Tahuayo_sites <- cbind(Per_Tahuayo_sites,
                                terra::extract(elevation_PE,
                                               Per_Tahuayo_sites)
                                )

# extract covs using points and add to _sites
covs_Per_Tahuayo_piloto_sites <- cbind(Per_Tahuayo_piloto_sites, terra::extract(elevation_PE, Per_Tahuayo_piloto_sites))



# get which are in and out
covs_Per_Tahuayo_sites$in_AP = st_intersects(covs_Per_Tahuayo_sites, AP_Tahuayo, sparse = FALSE)

covs_Per_Tahuayo_piloto_sites$in_AP = st_intersects(covs_Per_Tahuayo_piloto_sites, AP_Tahuayo, sparse = FALSE)




# make a map
mapview (elevation_PE, alpha=0.5) + 
  mapview (AP_Pacaya, color = "green", col.regions = "green", alpha = 0.5) +
  mapview (AP_Tahuayo, color = "green", col.regions = "green", alpha = 0.5) +
  mapview (covs_Per_Tahuayo_sites, zcol = "in_AP", col.regions =c("red","blue"), burst = TRUE) +   
  mapview (covs_Per_Tahuayo_piloto_sites, 
           zcol = "in_AP", 
           col.regions =c("blue"), 
           burst = TRUE) 

Yasuni data

Here we use the tables Ecu-13, Ecu-17, Ecu-18 y Ecu-20

Code
source("C:/CodigoR/WCS-CameraTrap/R/organiza_datos_v3.R")

AP_Yasuni <- read_sf("C:/CodigoR/Occu_APs/shp/Yasuni/WDPA_WDOECM_May2025_Public_186_shp-polygons.shp")

### Ecu 17, Ecu 18, ECU 20, Ecu 22  

# load data and make array_locID column
Ecu_13 <- loadproject("F:/WCS-CameraTrap/data/BDcorregidas/Ecuador/ECU-013.xlsx") |> mutate(array_locID=paste("Ecu_13", locationID, sep="_"))
Ecu_17 <- loadproject("F:/WCS-CameraTrap/data/BDcorregidas/Ecuador/ECU-017.xlsx") |> mutate(array_locID=paste("Ecu_17", locationID, sep="_"))
Ecu_18 <- loadproject("F:/WCS-CameraTrap/data/BDcorregidas/Ecuador/ECU-018.xlsx")|> mutate(array_locID=paste("Ecu_18", locationID, sep="_"))
Ecu_20 <- loadproject("F:/WCS-CameraTrap/data/BDcorregidas/Ecuador/ECU-020_Fix.xlsx")|> mutate(array_locID=paste("Ecu_20", locationID, sep="_"))
# Ecu_21 <- loadproject("F:/WCS-CameraTrap/data/BDcorregidas/Ecuador/ECU-021.xlsx") |> mutate(array_locID=paste("Ecu_14", locationID, sep="_"))
Ecu_22 <- loadproject("F:/WCS-CameraTrap/data/BDcorregidas/Ecuador/ECU-022.xlsx")|> mutate(array_locID=paste("Ecu_22", locationID, sep="_"))



# get sites
Ecu_13_sites <- get.sites("F:/WCS-CameraTrap/data/BDcorregidas/Ecuador/ECU-013.xlsx")
Ecu_17_sites <- get.sites("F:/WCS-CameraTrap/data/BDcorregidas/Ecuador/ECU-017.xlsx")
Ecu_18_sites <- get.sites("F:/WCS-CameraTrap/data/BDcorregidas/Ecuador/ECU-018.xlsx")
Ecu_20_sites <- get.sites("F:/WCS-CameraTrap/data/BDcorregidas/Ecuador/ECU-020_Fix.xlsx")
# Ecu_21_sites <- get.sites("F:/WCS-CameraTrap/data/BDcorregidas/Ecuador/ECU-021.xlsx")
Ecu_22_sites <- get.sites("F:/WCS-CameraTrap/data/BDcorregidas/Ecuador/ECU-022.xlsx")




# get elevation map
elevation_EC <- rast(get_elev_raster(Ecu_17_sites, z = 7)) #z =1-14
bb <-  st_as_sfc(st_bbox(elevation_EC)) # make bounding box 




# extract covs using points and add to _sites
covs_Ecu_13_sites <- cbind(Ecu_13_sites, terra::extract(elevation_EC, Ecu_13_sites))
covs_Ecu_17_sites <- cbind(Ecu_17_sites, terra::extract(elevation_EC, Ecu_17_sites))
covs_Ecu_18_sites <- cbind(Ecu_18_sites, terra::extract(elevation_EC, Ecu_18_sites))
covs_Ecu_20_sites <- cbind(Ecu_20_sites, terra::extract(elevation_EC, Ecu_20_sites))
#covs_Ecu_21_sites <- cbind(Ecu_21_sites, terra::extract(elevation_17, Ecu_21_sites))
covs_Ecu_22_sites <- cbind(Ecu_22_sites, terra::extract(elevation_EC, Ecu_22_sites))

# get which are in and out
covs_Ecu_13_sites$in_AP = st_intersects(covs_Ecu_13_sites, AP_Yasuni, sparse = FALSE)
covs_Ecu_17_sites$in_AP = st_intersects(covs_Ecu_17_sites, AP_Yasuni, sparse = FALSE)
covs_Ecu_18_sites$in_AP = st_intersects(covs_Ecu_18_sites, AP_Yasuni, sparse = FALSE)
covs_Ecu_20_sites$in_AP = st_intersects(covs_Ecu_20_sites, AP_Yasuni, sparse = FALSE)
#covs_Ecu_21_sites$in_AP = st_intersects(covs_Ecu_21_sites, AP_Yasuni, sparse = FALSE)
covs_Ecu_22_sites$in_AP = st_intersects(covs_Ecu_22_sites, AP_Yasuni, sparse = FALSE)

# covs_Ecu_16_sites$in_AP = st_intersects(covs_Ecu_16_sites, AP_Llanganates, sparse = FALSE)



# make a map
mapview (elevation_EC, alpha=0.5) + 
  mapview (AP_Yasuni, color = "green", col.regions = "green", alpha = 0.5) +
  mapview (covs_Ecu_13_sites, zcol = "in_AP", col.regions =c("red"), burst = TRUE) +
  mapview (covs_Ecu_17_sites, zcol = "in_AP", col.regions =c("red","blue"), burst = TRUE) +
  mapview (covs_Ecu_18_sites, zcol = "in_AP", col.regions =c("red"), burst = TRUE) +
  mapview (covs_Ecu_20_sites, zcol = "in_AP", col.regions =c("red","blue"), burst = TRUE) +
#  mapview (covs_Ecu_21_sites, zcol = "in_AP", col.regions =c("red"), burst = TRUE) +
  mapview (covs_Ecu_22_sites, zcol = "in_AP", burst = TRUE, col.regions = c("red") ) #+
  # mapview (covs_Ecu_16_sites, zcol = "in_AP", burst = TRUE, col.regions =c("red","blue")) 

Llanganates data

Here we use the tables Ecu-14, Ecu-15 y Ecu-16.

Code
source("C:/CodigoR/WCS-CameraTrap/R/organiza_datos_v3.R")

FLII2016 <- rast("C:/CodigoR/WCS_2024/FLI/raster/FLII_final/FLII_2016.tif")


AP_Llanganates <- read_sf("C:/CodigoR/Occu_APs/shp/Llanganates/WDPA_WDOECM_May2025_Public_97512_shp-polygons.shp")

### Ecu 14, Ecu 15  y Ecu 16

# load data and make array_locID column
Ecu_14 <- loadproject("F:/WCS-CameraTrap/data/BDcorregidas/Ecuador/ECU-014.xlsx") |> mutate(array_locID=paste("Ecu_14", locationID, sep="_"))
29 cameras in Cameras. 
 29 cameras in Deployment. 
 29 deployments in Deployment. 
 29 points in Deployment. 
 29 cameras in Images. 
 29 points in Images. 
[1] "dates ok"
year: 2015 
 Jaguar_Design: no 
Code
Ecu_15 <- loadproject("F:/WCS-CameraTrap/data/BDcorregidas/Ecuador/ECU-015.xlsx")|> mutate(array_locID=paste("Ecu_15", locationID, sep="_"))
29 cameras in Cameras. 
 29 cameras in Deployment. 
 30 deployments in Deployment. 
 30 points in Deployment. 
 30 cameras in Images. 
 30 points in Images. 
[1] "dates ok"
year: 2016 
 Jaguar_Design: no 
Code
Ecu_16 <- loadproject("F:/WCS-CameraTrap/data/BDcorregidas/Ecuador/ECU-016.xlsx")|> mutate(array_locID=paste("Ecu_16", locationID, sep="_"))
29 cameras in Cameras. 
 28 cameras in Deployment. 
 28 deployments in Deployment. 
 28 points in Deployment. 
 28 cameras in Images. 
 28 points in Images. 
[1] "dates ok"
year: 2016 
 Jaguar_Design: no 
Code
# get sites
Ecu_14_sites <- get.sites("F:/WCS-CameraTrap/data/BDcorregidas/Ecuador/ECU-014.xlsx")
Ecu_15_sites <- get.sites("F:/WCS-CameraTrap/data/BDcorregidas/Ecuador/ECU-015.xlsx")
Ecu_16_sites <- get.sites("F:/WCS-CameraTrap/data/BDcorregidas/Ecuador/ECU-016.xlsx")




# get elevation map
elevation_14 <- rast(get_elev_raster(Ecu_14_sites, z = 9)) #z =1-14
bb <-  st_as_sfc(st_bbox(elevation_14)) # make bounding box 




# extract covs using points and add to _sites
covs_Ecu_14_sites <- cbind(Ecu_14_sites, terra::extract(elevation_14, Ecu_14_sites))

covs_Ecu_15_sites <- cbind(Ecu_15_sites, terra::extract(elevation_14, Ecu_15_sites))

covs_Ecu_16_sites <- cbind(Ecu_16_sites, terra::extract(elevation_14, Ecu_16_sites))

# get which are in and out
covs_Ecu_14_sites$in_AP = st_intersects(covs_Ecu_14_sites, AP_Llanganates, sparse = FALSE)

covs_Ecu_15_sites$in_AP = st_intersects(covs_Ecu_15_sites, AP_Llanganates, sparse = FALSE)

covs_Ecu_16_sites$in_AP = st_intersects(covs_Ecu_16_sites, AP_Llanganates, sparse = FALSE)



# make a map
mapview (elevation_14, alpha=0.7) + 
  mapview (AP_Llanganates, color = "green", col.regions = "green", alpha = 0.5) +
  mapview (covs_Ecu_14_sites, zcol = "in_AP", col.regions =c("red","blue"), burst = TRUE) +
  mapview (covs_Ecu_15_sites, zcol = "in_AP", burst = TRUE, col.regions = c("blue") )+
  mapview (covs_Ecu_16_sites, zcol = "in_AP", burst = TRUE, col.regions =c("red","blue")) 

Pacoche 2014 data

Here we use the tables Pacoche_DL_CT-RVP-2014

Camera trap operation data and detection history

Code
# # Join 3 tables
# # fix count in ECU 13, 17, 22,
# Ecu_13$Count <- as.character(Ecu_13$Count)
# Ecu_17$Count <- as.character(Ecu_17$Count)
# Ecu_22$Count <- as.character(Ecu_22$Count)
# 
# Ecu_full <- Ecu_13 |> full_join(Ecu_17) |> 
#                       full_join(Ecu_18) |> 
#                       full_join(Ecu_20) |> 
# #                      full_join(Ecu_21) |> 
#                       full_join(Ecu_22)
# 
# ###### Bolivia
# 
# Bol_full <- Bol_Madidi_1  |> 
#    full_join(Bol_Madidi_2) |> 
#    full_join(Bol_Madidi_3) |> 
#    full_join(Bol_Madidi_4) 
# # change camera Id by point. two cameras in one
# Bol_full <- Bol_full |> mutate(Camera_Id=Point.x)


# # Ecu_18$Count <- as.numeric(Ecu_18$Count)
# Per_Tahuayo_piloto$Longitude <- as.numeric(Per_Tahuayo_piloto$Longitude)
# Per_Tahuayo_piloto$Latitude <- as.numeric(Per_Tahuayo_piloto$Latitude)
# 
# 
# Per_full <- Per_Tahuayo|> 
#   full_join(Per_Tahuayo_piloto) #|> 
#                       # full_join(Ecu_18) |> 
#                       # full_join(Ecu_20) |> 
#                       # full_join(Ecu_21) |> 
#                       # full_join(Ecu_22)
# 
# # rename camera id
# # Per_full$camid <- Per_full$`Camera_Id`
# 
# Ecu_full$Count <- as.numeric(Ecu_full$Count)
# Per_full$Count <- as.numeric(Per_full$Count)


#################### Ecuador Llanganates

# Join 3 tables
Ecu_Llanganates <- Ecu_14 |> full_join(Ecu_15) |> full_join(Ecu_16)


# make columns equal to 46
# Ecu_full <- Ecu_full[,-47]
# Col_18 <- Col_18[,-47]
# Ecu_Llanganates <- Ecu_Llanganates[,-c(50,49,48,47)]

##################################
data_full <- Ecu_Llanganates # Bol_full# rbind(Ecu_full, 
                   # Per_full,
                   # Bol_full,
                   # Col_18,
                   # Ecu_Llanganates)


# fix date format
# 
# Formatting a Date object
data_full$start_date <- as.Date(data_full$"start_date", "%Y/%m/%d")
data_full$start_date <- format(data_full$start_date, "%Y-%m-%d")

data_full$end_date <- as.Date(data_full$"end_date", "%Y/%m/%d")
data_full$end_date <- format(data_full$end_date, "%Y-%m-%d")

data_full$eventDate <- as.Date(data_full$"Date_Time_Captured", "%Y/%m/%d")
data_full$eventDate <- format(data_full$eventDate, "%Y-%m-%d")

# Per_full$eventDateTime <- ymd_hms(paste(Per_full$"photo_date", Per_full$"photo_time", sep=" "))
data_full$eventDateTime <- ymd_hms(data_full$"Date_Time_Captured")

###############################
# remove duplicated cameras
################################
# ind1 <- which(data_full$Camera_Id=="ECU-020-C0027")
# ind2 <- which(data_full$Camera_Id=="ECU-020-C0006")
# data_full <- data_full[-ind1,]
# data_full <- data_full[-ind2,]


# filter 2021 and make uniques
CToperation  <- data_full |> dplyr::group_by(Camera_Id) |> #(array_locID) |> 
                           mutate(minStart=start_date, maxEnd=end_date) |> distinct(Longitude, Latitude, minStart, maxEnd) |> dplyr::ungroup()
# remove one duplicated
# View(CToperation)
# CToperation <- CToperation[-15,]

# Duplicated Madidi
# 98 107, 97 104, 90 102, 81 87, 74 82
# M3-19: M3-21: M4-10: M4-12: M4-18:  From Madidi
# CToperation <- CToperation[-c(107, 104, 102, 87, 82),]

#CToperation[231,3] <- "-4.482831" #Latitude
#CToperation[93,3] <- "-0.5548211" #Latitude
#CToperation[93,2] <- "-76.48333"

# duplicated in llanganates
CToperation <- CToperation[-36,] 

### Check duplicated
# View(as.data.frame(sort(table(CToperation$Latitude))))
# View(as.data.frame(sort(table(CToperation$Longitude))))
# View(as.data.frame(table(CToperation$Camera_Id)))

# CToperation <- CToperation[-c(90,94),]
# Latitude -4.48283
# Latitude -0.554820969700813
# Longitude -76.4833290316164

# Generamos la matríz de operación de las cámaras

camop <- cameraOperation(CTtable= CToperation, # Tabla de operación
                         stationCol= "Camera_Id", # Columna que define la estación
                         setupCol= "minStart", #Columna fecha de colocación
                         retrievalCol= "maxEnd", #Columna fecha de retiro
                         #hasProblems= T, # Hubo fallos de cámaras
                         dateFormat= "%Y-%m-%d")#, #, # Formato de las fechas
                         #cameraCol="Camera_Id")
                         # sessionCol= "Year")

# Generar las historias de detección ---------------------------------------
## remove plroblem species

# Per_full$scientificName <- paste(Per_full$genus, Per_full$species, sep=" ")

#### remove NAs and setups
# ind <- which(is.na(data_full$scientificName))
# data_full <- data_full[-ind,]
# ind <- which(Per_full$scientificName=="NA NA")
# Per_full <- Per_full[-ind,]

# ind <- which(Per_full$scientificName=="Set up")
# Per_full <- Per_full[-ind,]
# 
# ind <- which(Per_full$scientificName=="Blank")
# Per_full <- Per_full[-ind,]
# 
# ind <- which(Per_full$scientificName=="Unidentifiable")
# Per_full <- Per_full[-ind,]


DetHist_list <- lapply(unique(data_full$scientificName), FUN = function(x) {
  detectionHistory(
    recordTable         = data_full, # abla de registros
    camOp                = camop, # Matriz de operación de cámaras
    stationCol           = "Camera_Id",
    speciesCol           = "scientificName",
    recordDateTimeCol    = "eventDateTime",
    recordDateTimeFormat  = "%Y-%m-%d %H:%M:%S",
    species              = x,     # la función reemplaza x por cada una de las especies
    occasionLength       = 7, # Colapso de las historias a 10 ías
    day1                 = "station", # "survey" a specific date, "station", #inicie en la fecha de cada survey
    datesAsOccasionNames = FALSE,
    includeEffort        = TRUE,
    scaleEffort          = FALSE,
    #unmarkedMultFrameInput=TRUE
    timeZone             = "America/Bogota" 
    )
  }
)

# names
names(DetHist_list) <- unique(data_full$scientificName)

# Finalmente creamos una lista nueva donde estén solo las historias de detección
ylist <- lapply(DetHist_list, FUN = function(x) x$detection_history)
# otra lista con effort scaled
efort <- lapply(DetHist_list, FUN = function(x) x$effort)

# number of observetions per sp, collapsed to 7 days
# lapply(ylist, sum, na.rm = TRUE)

Arrange spatial covariates

The standard EPSG code for a Lambert Azimuthal Equal-Area projection for South America is EPSG:10603 (WGS 84 / GLANCE South America). This projection is specifically designed for the continent and has its center located around the central meridian for the region. The units are meters.

FLII scores range from 0 (lowest integrity) to 10 (highest). Grantham discretized this range to define three broad illustrative categories: low (≤6.0); medium (>6.0 and <9.6); and high integrity (≥9.6).

Code
# #transform coord data to Lambert Azimuthal Equal-Area
# AP_Tahuayo_UTM <- st_transform(AP_Tahuayo, "EPSG:10603")
# # Convert to LINESTRING
# AP_Tahuayo_UTM_line <- st_cast(AP_Tahuayo_UTM,"MULTILINESTRING")# "LINESTRING")
# #transform Yasuni to Lambert Azimuthal Equal-Area
# AP_Yasuni_UTM <- st_transform(AP_Yasuni, "EPSG:10603")
# # Convert to LINESTRING
# AP_Yasuni_UTM_line <- st_cast(AP_Yasuni_UTM, "MULTILINESTRING")

#transform Yasuni to Lambert Azimuthal Equal-Area
AP_Llanganates_UTM <- st_transform(AP_Llanganates, "EPSG:10603")
# Convert to LINESTRING
AP_Llanganates_UTM_line <- st_cast(AP_Llanganates_UTM, "MULTILINESTRING")

# # Plantas
# AP_PlantasMed_UTM <- st_transform(AP_PlantasMed, "EPSG:10603")
# 
# #Llanganates
# AP_Llanganates_UTM <- st_transform(AP_Llanganates, "EPSG:10603")


############## sf AP Union 
AP_merged_sf_UTM <- AP_Llanganates_UTM# AP_Madidi_UTM# st_union(
                             # AP_Yasuni_UTM,
                             # AP_Tahuayo_UTM,
                             # AP_Madidi_UTM,
                             # AP_PlantasMed_UTM,
                             # AP_Llanganates_UTM
                             # )

AP_merged_line <- st_cast(AP_merged_sf_UTM, to="MULTILINESTRING")


# make sf() from data table
data_full_sf <- CToperation |> 
    st_as_sf(coords = c("Longitude", "Latitude"), 
              crs = 4326)

# get the elevation point from AWS
elev_data <- elevatr::get_elev_point(locations = data_full_sf, 
                                     src = "aws",
                                     z=10)
Mosaicing & Projecting
Note: Elevation units are in meters
Code
# extract elev and paste to table
data_full_sf$elev <- elev_data$elevation
str(data_full_sf$elev)
 num [1:86] 639 1151 732 607 1141 ...
Code
# extract in AP
data_full_sf$in_AP = as.factor(st_intersects(data_full_sf, AP_Llanganates, sparse = FALSE))

in_AP <- as.numeric((st_drop_geometry(data_full_sf$in_AP)))

# extract FLII
data_full_sf$FLII <- terra::extract(FLII2016, data_full_sf)[,2]
str(data_full_sf$FLII)
 num [1:86] 9.94 9.98 9.76 9.81 9.57 ...
Code
# Replace all NAs with min flii in a numeric column
data_full_sf$FLII[is.na(data_full_sf$FLII)] <- min(data_full_sf$FLII, na.rm = TRUE)

# mapview(full_sites_14_15_16_sf, zcol = "in_AP", burst = TRUE)

# Transform coord to Lambert Azimuthal Equal-Area
data_full_sf_UTM <- st_transform(data_full_sf, "EPSG:10603")


coords <- st_coordinates(data_full_sf_UTM)
#str(coords)

#### fix duplicated coord
# -1840583.53296873  en x
# -1842515.36969736  en x
# 1547741.44311964  en y
# 1541202.24796904 en y

# which(coords[,1]=="-1840583.53296873")
# which(coords[,1]=="-1842515.36969736")
# which(coords[,2]=="1547741.44311964")
# which(coords[,2]=="1541202.24796904")

# make Ecu_14_15_16 an sf object
#    cam_sf <- st_as_sf(Ecu_14_15_16, coords = c("lon","lat"))   #crs="EPSG:4326")
    #--- set CRS ---#
#    st_crs(cam_sf) <- 4326




# Calculate the distance
#multiplic <- full_sites_14_15_16_sf_UTM |> mutate(multiplic= as.numeric(in_AP)) 
multiplic=ifelse(data_full_sf_UTM$in_AP=="TRUE",-1,1)
data_full_sf_UTM$border_dist <- as.numeric(st_distance(data_full_sf_UTM, AP_Llanganates_UTM_line) * multiplic )
# print(border_dist)

# convert true false to inside 1, outside 0
data_full_sf_UTM <- data_full_sf_UTM |>
  mutate(in_AP = case_when(
    str_detect(in_AP, "TRUE") ~ 1, # "inside_AP",
    str_detect(in_AP, "FALSE") ~ 0 #"outside_AP"
  )) |> mutate(in_AP=as.factor(in_AP))


hist(data_full_sf_UTM$border_dist)

Code
hist(data_full_sf_UTM$elev)

Prepare the model

TipData in a 3D array

The data must be placed in a three-dimensional array with dimensions corresponding to species, sites, and replicates in that order.

The function sfMsPGOcc

Fits multi-species spatial occupancy models with species correlations (i.e., a spatially-explicit joint species distribution model with imperfect detection). We use Polya-Gamma latent variables and a spatial factor modeling approach. Currently, models are implemented using a Nearest Neighbor Gaussian Process.

Code
# Detection-nondetection data ---------
# Species of interest, can select individually
# curr.sp <- sort(unique(Ecu_14_15_16$.id))# c('BAWW', 'BLJA', 'GCFL')
# sort(names(DetHist_list))
selected.sp <-  c(
# "Atelocynus microtis" ,
#"Coendou prehensilis" ,
"Cuniculus paca",           
"Cuniculus taczanowskii",
"Dasyprocta fuliginosa",      
"Dasypus novemcinctus" ,    
"Didelphis pernigra",    
"Eira barbara",  
"Herpailurus yagouaroundi",
"Leopardus pardalis",    
"Leopardus tigrinus" ,
"Leopardus wiedii",         
#"Mazama americana",
"Mazama murelia",
"Mazama rufina" ,
"Mazama zamora" ,
#"Mazama gouazoubira",
#"Mitu tuberosum" ,
#"Myoprocta pratti",
"Nasuella olivacea" ,
#"Myrmecophaga tridactyla",
#"Nasua nasua" ,
# "Mazama americana",         
# "Myotis myotis",           
# "Nasua narica",             
# "Odocoileus virginianus",   
"Odocoileus ustus",
"Panthera onca" ,
# "Procyon cancrivorus" ,
"Pecari tajacu",    
#"Penelope jacquacu" ,
#"Priodontes maximus" ,
#"Procyon cancrivorus",      
# "Psophia leucoptera",
"Pudu mephistophiles" ,
"Puma concolor" ,
# "Puma yagouaroundi",        
# "Rattus rattus" ,
# "Roedor sp.",
# "Sciurus sp.",       
# "Sus scrofa",               
# "Sylvilagus brasiliensis",  
#"Tamandua tetradactyla",   
"Tapirus pinchaque" ,
#"Tapirus terrestris",
"Tayassu pecari",
"Tremarctos ornatus" 
#"Tinamus major"            
              )

# y.msom <- y[which(sp.codes %in% selected.sp), , ]
# str(y.msom)

# Use selection
y.selected <- ylist[selected.sp]   

#####################################
#### three-dimensional array with dimensions corresponding to:
#### species, sites, and replicates
#####################################

# 1. Load the abind library to make arrays easily 
library(abind)
my_array_abind <- abind(y.selected, # start from list
                        along = 3, # 3D array
                        use.first.dimnames=TRUE) # keep names

# Transpose the array to have:
# species, sites, and sampling occasions in that order
# The new order is (3rd dim, 1st dim, 2nd dim)
transposed_array <- aperm(my_array_abind, c(3, 1, 2))

#### site covs
sitecovs <- as.data.frame(st_drop_geometry(
                    data_full_sf_UTM[,5:8]))

 sitecovs[, 1] <- as.vector((sitecovs[,1]))   # scale numeric covariates
 sitecovs[, 1] <- as.numeric((sitecovs[,2]))   # scale numeric covariates
 sitecovs[, 3] <- as.vector((sitecovs[,3]))   # scale numeric covariates
 sitecovs[, 4] <- as.vector((sitecovs[,4]))   # scale numeric covariates
 # sitecovs$fact <- factor(c("A", "A", "B"))    # categorical covariate

names(sitecovs) <- c("elev", "in_AP", "FLII", "border_dist")

# check consistancy equal number of spatial covariates and rows in data
# identical(nrow(ylist[[1]]), nrow(covars)) 

# Base de datos para los análisis -----------------------------------------

# match the names to "y"  "occ.covs" "det.covs" "coords" 
data_list <- list(y = transposed_array, # Historias de detección
                  occ.covs = sitecovs, # covs de sitio
                  det.covs  = list(effort = DetHist_list[[1]]$effort),
                  coords = st_coordinates(data_full_sf_UTM)
                  )  # agregamos el esfuerzo de muestreo como covariable de observación

Running the model

We let spOccupancy set the initial values by default based on the prior distributions.

Code
# Running the model

# 3. 1 Modelo multi-especie  -----------------------------------------

# 2. Model fitting --------------------------------------------------------
# Fit a non-spatial, multi-species occupancy model. 
out.null <- msPGOcc(occ.formula = ~ scale(elev) +
                               scale(border_dist) + 
                               scale(FLII) , 
               det.formula = ~ scale(effort) , # Ordinal.day + I(Ordinal.day^2) + Year
                 data = data_list, 
                 n.samples = 6000, 
                 n.thin = 10, 
                 n.burn = 1000, 
                 n.chains = 3,
                 n.report = 1000);beep(sound = 4)
----------------------------------------
    Preparing to run the model
----------------------------------------
No prior specified for beta.comm.normal.
Setting prior mean to 0 and prior variance to 2.72
No prior specified for alpha.comm.normal.
Setting prior mean to 0 and prior variance to 2.72
No prior specified for tau.sq.beta.ig.
Setting prior shape to 0.1 and prior scale to 0.1
No prior specified for tau.sq.alpha.ig.
Setting prior shape to 0.1 and prior scale to 0.1
z is not specified in initial values.
Setting initial values based on observed data
beta.comm is not specified in initial values.
Setting initial values to random values from the prior distribution
alpha.comm is not specified in initial values.
Setting initial values to random values from the prior distribution
tau.sq.beta is not specified in initial values.
Setting initial values to random values between 0.5 and 10
tau.sq.alpha is not specified in initial values.
Setting to initial values to random values between 0.5 and 10
beta is not specified in initial values.
Setting initial values to random values from the community-level normal distribution
alpha is not specified in initial values.
Setting initial values to random values from the community-level normal distribution
----------------------------------------
    Model description
----------------------------------------
Multi-species Occupancy Model with Polya-Gamma latent
variable fit with 86 sites and 21 species.

Samples per Chain: 6000 
Burn-in: 1000 
Thinning Rate: 10 
Number of Chains: 3 
Total Posterior Samples: 1500 

Source compiled with OpenMP support and model fit using 1 thread(s).

----------------------------------------
    Chain 1
----------------------------------------
Sampling ... 
Sampled: 1000 of 6000, 16.67%
-------------------------------------------------
Sampled: 2000 of 6000, 33.33%
-------------------------------------------------
Sampled: 3000 of 6000, 50.00%
-------------------------------------------------
Sampled: 4000 of 6000, 66.67%
-------------------------------------------------
Sampled: 5000 of 6000, 83.33%
-------------------------------------------------
Sampled: 6000 of 6000, 100.00%
----------------------------------------
    Chain 2
----------------------------------------
Sampling ... 
Sampled: 1000 of 6000, 16.67%
-------------------------------------------------
Sampled: 2000 of 6000, 33.33%
-------------------------------------------------
Sampled: 3000 of 6000, 50.00%
-------------------------------------------------
Sampled: 4000 of 6000, 66.67%
-------------------------------------------------
Sampled: 5000 of 6000, 83.33%
-------------------------------------------------
Sampled: 6000 of 6000, 100.00%
----------------------------------------
    Chain 3
----------------------------------------
Sampling ... 
Sampled: 1000 of 6000, 16.67%
-------------------------------------------------
Sampled: 2000 of 6000, 33.33%
-------------------------------------------------
Sampled: 3000 of 6000, 50.00%
-------------------------------------------------
Sampled: 4000 of 6000, 66.67%
-------------------------------------------------
Sampled: 5000 of 6000, 83.33%
-------------------------------------------------
Sampled: 6000 of 6000, 100.00%
Code
summary(out.null, level = 'community')

Call:
msPGOcc(occ.formula = ~scale(elev) + scale(border_dist) + scale(FLII), 
    det.formula = ~scale(effort), data = data_list, n.samples = 6000, 
    n.report = 1000, n.burn = 1000, n.thin = 10, n.chains = 3)

Samples per Chain: 6000
Burn-in: 1000
Thinning Rate: 10
Number of Chains: 3
Total Posterior Samples: 1500
Run Time (min): 0.9792

----------------------------------------
    Community Level
----------------------------------------
Occurrence Means (logit scale): 
                      Mean     SD    2.5%     50%   97.5%   Rhat  ESS
(Intercept)        -3.0650 0.3533 -3.8095 -3.0589 -2.3914 1.0084  597
scale(elev)        -0.5995 0.2846 -1.2094 -0.5882 -0.0428 1.0054 1270
scale(border_dist) -0.0811 0.2923 -0.6524 -0.0752  0.4841 1.0017 1278
scale(FLII)         0.6848 0.2486  0.2177  0.6769  1.1824 1.0062 1010

Occurrence Variances (logit scale): 
                     Mean     SD   2.5%    50%  97.5%   Rhat  ESS
(Intercept)        1.6647 0.8209 0.6004 1.5120 3.6740 1.0009  756
scale(elev)        0.9297 0.6043 0.2120 0.7936 2.3770 1.0099  789
scale(border_dist) 0.9130 0.5669 0.1898 0.7722 2.4033 1.0055 1032
scale(FLII)        0.7133 0.4030 0.2091 0.6264 1.7299 1.0262 1006

Detection Means (logit scale): 
                 Mean     SD    2.5%     50%   97.5%   Rhat ESS
(Intercept)   -1.4554 0.2307 -1.9611 -1.4402 -1.0398 1.0041 796
scale(effort)  0.3996 0.1586  0.1134  0.3907  0.7366 1.0031 999

Detection Variances (logit scale): 
                Mean     SD   2.5%    50%  97.5%   Rhat ESS
(Intercept)   0.7007 0.4830 0.1716 0.5816 2.0033 1.0043 508
scale(effort) 0.1830 0.1526 0.0379 0.1425 0.5669 1.0084 977
Code
# Fit a non-spatial, Latent Factor Multi-Species Occupancy Model. 
  out.lfMs <- msPGOcc(occ.formula = ~ scale(elev) +
                               scale(border_dist) + 
                               scale(FLII) , 
               det.formula = ~ scale(effort), # Ordinal.day + I(Ordinal.day^2) + Year
                 data = data_list, 
                 n.omp.threads = 6,
                 n.samples = 6000, 
                 n.factors = 5, # balance of rare sp. and run time
                 n.thin = 10, 
                 n.burn = 1000, 
                 n.chains = 3,
                 n.report = 1000);beep(sound = 4)
----------------------------------------
    Preparing to run the model
----------------------------------------
Warning in msPGOcc(occ.formula = ~scale(elev) + scale(border_dist) +
scale(FLII), : 'n.factors' is not an argument
No prior specified for beta.comm.normal.
Setting prior mean to 0 and prior variance to 2.72
No prior specified for alpha.comm.normal.
Setting prior mean to 0 and prior variance to 2.72
No prior specified for tau.sq.beta.ig.
Setting prior shape to 0.1 and prior scale to 0.1
No prior specified for tau.sq.alpha.ig.
Setting prior shape to 0.1 and prior scale to 0.1
z is not specified in initial values.
Setting initial values based on observed data
beta.comm is not specified in initial values.
Setting initial values to random values from the prior distribution
alpha.comm is not specified in initial values.
Setting initial values to random values from the prior distribution
tau.sq.beta is not specified in initial values.
Setting initial values to random values between 0.5 and 10
tau.sq.alpha is not specified in initial values.
Setting to initial values to random values between 0.5 and 10
beta is not specified in initial values.
Setting initial values to random values from the community-level normal distribution
alpha is not specified in initial values.
Setting initial values to random values from the community-level normal distribution
----------------------------------------
    Model description
----------------------------------------
Multi-species Occupancy Model with Polya-Gamma latent
variable fit with 86 sites and 21 species.

Samples per Chain: 6000 
Burn-in: 1000 
Thinning Rate: 10 
Number of Chains: 3 
Total Posterior Samples: 1500 

Source compiled with OpenMP support and model fit using 6 thread(s).

----------------------------------------
    Chain 1
----------------------------------------
Sampling ... 
Sampled: 1000 of 6000, 16.67%
-------------------------------------------------
Sampled: 2000 of 6000, 33.33%
-------------------------------------------------
Sampled: 3000 of 6000, 50.00%
-------------------------------------------------
Sampled: 4000 of 6000, 66.67%
-------------------------------------------------
Sampled: 5000 of 6000, 83.33%
-------------------------------------------------
Sampled: 6000 of 6000, 100.00%
----------------------------------------
    Chain 2
----------------------------------------
Sampling ... 
Sampled: 1000 of 6000, 16.67%
-------------------------------------------------
Sampled: 2000 of 6000, 33.33%
-------------------------------------------------
Sampled: 3000 of 6000, 50.00%
-------------------------------------------------
Sampled: 4000 of 6000, 66.67%
-------------------------------------------------
Sampled: 5000 of 6000, 83.33%
-------------------------------------------------
Sampled: 6000 of 6000, 100.00%
----------------------------------------
    Chain 3
----------------------------------------
Sampling ... 
Sampled: 1000 of 6000, 16.67%
-------------------------------------------------
Sampled: 2000 of 6000, 33.33%
-------------------------------------------------
Sampled: 3000 of 6000, 50.00%
-------------------------------------------------
Sampled: 4000 of 6000, 66.67%
-------------------------------------------------
Sampled: 5000 of 6000, 83.33%
-------------------------------------------------
Sampled: 6000 of 6000, 100.00%
Code
summary(out.lfMs, level = 'community')

Call:
msPGOcc(occ.formula = ~scale(elev) + scale(border_dist) + scale(FLII), 
    det.formula = ~scale(effort), data = data_list, n.samples = 6000, 
    n.omp.threads = 6, n.report = 1000, n.burn = 1000, n.thin = 10, 
    n.chains = 3, n.factors = 5)

Samples per Chain: 6000
Burn-in: 1000
Thinning Rate: 10
Number of Chains: 3
Total Posterior Samples: 1500
Run Time (min): 0.9745

----------------------------------------
    Community Level
----------------------------------------
Occurrence Means (logit scale): 
                      Mean     SD    2.5%     50%   97.5%   Rhat  ESS
(Intercept)        -3.0293 0.3568 -3.7596 -3.0213 -2.2957 1.0092  552
scale(elev)        -0.6125 0.2900 -1.2266 -0.6039 -0.0593 1.0114  878
scale(border_dist) -0.0940 0.2894 -0.7026 -0.0887  0.4883 1.0059 1306
scale(FLII)         0.6911 0.2516  0.2068  0.6763  1.2234 1.0052 1001

Occurrence Variances (logit scale): 
                     Mean     SD   2.5%    50%  97.5%   Rhat ESS
(Intercept)        1.6327 0.8201 0.6526 1.4555 3.6301 1.0274 690
scale(elev)        0.8690 0.5509 0.2016 0.7397 2.2737 1.0080 769
scale(border_dist) 0.9220 0.5996 0.1627 0.7650 2.4355 1.0356 717
scale(FLII)        0.6812 0.3840 0.2150 0.5883 1.7032 1.0045 922

Detection Means (logit scale): 
                 Mean     SD    2.5%     50%   97.5%   Rhat  ESS
(Intercept)   -1.4684 0.2452 -1.9792 -1.4510 -1.0277 1.0109  657
scale(effort)  0.3963 0.1526  0.1225  0.3928  0.7262 1.0019 1216

Detection Variances (logit scale): 
                Mean     SD   2.5%    50%  97.5%   Rhat  ESS
(Intercept)   0.7257 0.4992 0.1739 0.5770 1.9867 1.0092  360
scale(effort) 0.1714 0.1326 0.0374 0.1338 0.5049 1.0036 1114
Code
# Fit a Spatial Factor Multi-Species Occupancy Model
# latent spatial factors.
tictoc::tic()
  out.sp <- sfMsPGOcc(occ.formula = ~ scale(elev) +
                               scale(border_dist) + 
                               scale(FLII) , 
               det.formula = ~ scale(effort), # Ordinal.day + I(Ordinal.day^2) + Year,            
                      data = data_list, 
                      n.omp.threads = 6,
                      n.batch = 600, 
                      batch.length = 25, # iter=600*25
                      n.thin = 10, 
                      n.burn = 5000, 
                      n.chains = 3,
                      NNGP = TRUE,
                      n.factors = 5, # balance of rare sp. and run time
                      n.neighbors = 15,
                      cov.model = 'exponential',
                      n.report = 1000);beep(sound = 4)
----------------------------------------
    Preparing to run the model
----------------------------------------
No prior specified for beta.comm.normal.
Setting prior mean to 0 and prior variance to 2.72
No prior specified for alpha.comm.normal.
Setting prior mean to 0 and prior variance to 2.72
No prior specified for tau.sq.beta.
Using an inverse-Gamma prior with prior shape 0.1 and prior scale 0.1
No prior specified for tau.sq.alpha.
Using an inverse-Gamma prior with prior shape 0.1 and prior scale 0.1
No prior specified for phi.unif.
Setting uniform bounds based on the range of observed spatial coordinates.
z is not specified in initial values.
Setting initial values based on observed data
beta.comm is not specified in initial values.
Setting initial values to random values from the prior distribution
alpha.comm is not specified in initial values.
Setting initial values to random values from the prior distribution
tau.sq.beta is not specified in initial values.
Setting initial values to random values between 0.5 and 10
tau.sq.alpha is not specified in initial values.
Setting initial values to random values between 0.5 and 10
beta is not specified in initial values.
Setting initial values to random values from the community-level normal distribution
alpha is not specified in initial values.
Setting initial values to random values from the community-level normal distribution
phi is not specified in initial values.
Setting initial value to random values from the prior distribution
lambda is not specified in initial values.
Setting initial values of the lower triangle to 0
----------------------------------------
    Building the neighbor list
----------------------------------------
----------------------------------------
Building the neighbors of neighbors list
----------------------------------------
----------------------------------------
    Model description
----------------------------------------
Spatial Factor NNGP Multi-species Occupancy Model with Polya-Gamma latent
variable fit with 86 sites and 21 species.

Samples per chain: 15000 (600 batches of length 25)
Burn-in: 5000 
Thinning Rate: 10 
Number of Chains: 3 
Total Posterior Samples: 3000 

Using the exponential spatial correlation model.

Using 5 latent spatial factors.
Using 15 nearest neighbors.

Source compiled with OpenMP support and model fit using 6 thread(s).

Adaptive Metropolis with target acceptance rate: 43.0
----------------------------------------
    Chain 1
----------------------------------------
Sampling ... 
Batch: 600 of 600, 100.00%
----------------------------------------
    Chain 2
----------------------------------------
Sampling ... 
Batch: 600 of 600, 100.00%
----------------------------------------
    Chain 3
----------------------------------------
Sampling ... 
Batch: 600 of 600, 100.00%
Code
tictoc::toc()
416.99 sec elapsed
Code
#########################
tictoc::tic()
  out.sp.cat <- sfMsPGOcc(occ.formula = ~ scale(elev) +
                               factor(in_AP) + 
                               scale(FLII) , 
               det.formula = ~ scale(effort), # Ordinal.day + I(Ordinal.day^2) + Year,            
                      data = data_list, 
                      n.omp.threads = 6,
                      n.batch = 600, 
                      batch.length = 25, # iter=600*25
                      n.thin = 10, 
                      n.burn = 5000, 
                      n.chains = 3,
                      NNGP = TRUE,
                      n.factors = 5, # balance of rare sp. and run time
                      n.neighbors = 15,
                      cov.model = 'exponential',
                      n.report = 1000);beep(sound = 4)
----------------------------------------
    Preparing to run the model
----------------------------------------
No prior specified for beta.comm.normal.
Setting prior mean to 0 and prior variance to 2.72
No prior specified for alpha.comm.normal.
Setting prior mean to 0 and prior variance to 2.72
No prior specified for tau.sq.beta.
Using an inverse-Gamma prior with prior shape 0.1 and prior scale 0.1
No prior specified for tau.sq.alpha.
Using an inverse-Gamma prior with prior shape 0.1 and prior scale 0.1
No prior specified for phi.unif.
Setting uniform bounds based on the range of observed spatial coordinates.
z is not specified in initial values.
Setting initial values based on observed data
beta.comm is not specified in initial values.
Setting initial values to random values from the prior distribution
alpha.comm is not specified in initial values.
Setting initial values to random values from the prior distribution
tau.sq.beta is not specified in initial values.
Setting initial values to random values between 0.5 and 10
tau.sq.alpha is not specified in initial values.
Setting initial values to random values between 0.5 and 10
beta is not specified in initial values.
Setting initial values to random values from the community-level normal distribution
alpha is not specified in initial values.
Setting initial values to random values from the community-level normal distribution
phi is not specified in initial values.
Setting initial value to random values from the prior distribution
lambda is not specified in initial values.
Setting initial values of the lower triangle to 0
----------------------------------------
    Building the neighbor list
----------------------------------------
----------------------------------------
Building the neighbors of neighbors list
----------------------------------------
----------------------------------------
    Model description
----------------------------------------
Spatial Factor NNGP Multi-species Occupancy Model with Polya-Gamma latent
variable fit with 86 sites and 21 species.

Samples per chain: 15000 (600 batches of length 25)
Burn-in: 5000 
Thinning Rate: 10 
Number of Chains: 3 
Total Posterior Samples: 3000 

Using the exponential spatial correlation model.

Using 5 latent spatial factors.
Using 15 nearest neighbors.

Source compiled with OpenMP support and model fit using 6 thread(s).

Adaptive Metropolis with target acceptance rate: 43.0
----------------------------------------
    Chain 1
----------------------------------------
Sampling ... 
Batch: 600 of 600, 100.00%
----------------------------------------
    Chain 2
----------------------------------------
Sampling ... 
Batch: 600 of 600, 100.00%
----------------------------------------
    Chain 3
----------------------------------------
Sampling ... 
Batch: 600 of 600, 100.00%
Code
tictoc::toc()
417.83 sec elapsed
Code
# tictoc::tic()
#   out.sp.gaus <- sfMsPGOcc(occ.formula = ~ scale(border_dist) , 
#                            det.formula = ~ scale(effort), # Ordinal.day + I(Ordinal.day^2) + Year,              
#                            data = data_list, 
#                            n.batch = 400, 
#                            batch.length = 25,
#                            n.thin = 5, 
#                            n.burn = 5000, 
#                            n.chains = 1,
#                            NNGP = TRUE,
#                            n.factors = 5,
#                            n.neighbors = 15,
#                            cov.model = 'gaussian',
#                            n.report = 100);beep(sound = 4)
# tictoc::toc()

# save the results to not run again
# save(out, file="C:/CodigoR/Occu_APs_all/blog/2025-10-15-analysis/result/result_2.R") # guardamos los resultados para no correr de nuevo
# save the results to not run again
# save(out.sp, file="C:/CodigoR/Occu_APs_all/blog/2025-10-15-analysis/result/sp_result_2.R") # guardamos los resultados para no correr de nuevo

# save(out.lfMs, file="C:/CodigoR/Occu_APs_all/blog/2025-10-15-analysis/result/lfms_result_2.R") # guardamos los resultados para no correr de nuevo


# load("C:/CodigoR/Occu_APs_all/blog/2025-10-15-analysis/result/sp_result_2.R")
# summary(fit.commu)

Model validation

We next perform a posterior predictive check using the Freeman-Tukey statistic grouping the data by sites. We summarize the posterior predictive check with the summary() function, which reports a Bayesian p-value. A Bayesian p-value that hovers around 0.5 indicates adequate model fit, while values less than 0.1 or greater than 0.9 suggest our model does not fit the data well (Hobbs and Hooten 2015). As always with a simulation-based analysis using MCMC, you will get numerically slightly different values.

Code
# 3. Model validation -----------------------------------------------------
# Perform a posterior predictive check to assess model fit. 
ppc.out <- ppcOcc(out.null, fit.stat = 'freeman-tukey', 
                  group = 1)
ppc.out.lfMs <- ppcOcc(out.lfMs, fit.stat = 'freeman-tukey', 
                  group = 1)
ppc.out.sp <- ppcOcc(out.sp, fit.stat = 'freeman-tukey',
                     group = 1)

# Calculate a Bayesian p-value as a simple measure of Goodness of Fit.
# Bayesian p-values between 0.1 and 0.9 indicate adequate model fit. 
summary(ppc.out)

Call:
ppcOcc(object = out.null, fit.stat = "freeman-tukey", group = 1)

Samples per Chain: 6000
Burn-in: 1000
Thinning Rate: 10
Number of Chains: 3
Total Posterior Samples: 1500

----------------------------------------
    Community Level
----------------------------------------
Bayesian p-value:  0.3896 

----------------------------------------
    Species Level
----------------------------------------
Cuniculus paca Bayesian p-value: 0.4727
Cuniculus taczanowskii Bayesian p-value: 0.3567
Dasyprocta fuliginosa Bayesian p-value: 0.3847
Dasypus novemcinctus Bayesian p-value: 0.316
Eira barbara Bayesian p-value: 0.546
Herpailurus yagouaroundi Bayesian p-value: 0.3833
Leopardus pardalis Bayesian p-value: 0.3707
Leopardus tigrinus Bayesian p-value: 0.422
Leopardus wiedii Bayesian p-value: 0.5167
Mazama murelia Bayesian p-value: 0.276
Mazama rufina Bayesian p-value: 0.404
Mazama zamora Bayesian p-value: 0.174
Nasuella olivacea Bayesian p-value: 0.5487
Odocoileus ustus Bayesian p-value: 0.1227
Panthera onca Bayesian p-value: 0.5553
Pecari tajacu Bayesian p-value: 0.3947
Pudu mephistophiles Bayesian p-value: 0.2347
Puma concolor Bayesian p-value: 0.3453
Tapirus pinchaque Bayesian p-value: 0.3827
Tayassu pecari Bayesian p-value: 0.4367
Tremarctos ornatus Bayesian p-value: 0.5373
Fit statistic:  freeman-tukey 
Code
summary(ppc.out.lfMs)

Call:
ppcOcc(object = out.lfMs, fit.stat = "freeman-tukey", group = 1)

Samples per Chain: 6000
Burn-in: 1000
Thinning Rate: 10
Number of Chains: 3
Total Posterior Samples: 1500

----------------------------------------
    Community Level
----------------------------------------
Bayesian p-value:  0.3911 

----------------------------------------
    Species Level
----------------------------------------
Cuniculus paca Bayesian p-value: 0.506
Cuniculus taczanowskii Bayesian p-value: 0.3713
Dasyprocta fuliginosa Bayesian p-value: 0.3847
Dasypus novemcinctus Bayesian p-value: 0.3347
Eira barbara Bayesian p-value: 0.522
Herpailurus yagouaroundi Bayesian p-value: 0.3947
Leopardus pardalis Bayesian p-value: 0.366
Leopardus tigrinus Bayesian p-value: 0.4087
Leopardus wiedii Bayesian p-value: 0.52
Mazama murelia Bayesian p-value: 0.276
Mazama rufina Bayesian p-value: 0.4333
Mazama zamora Bayesian p-value: 0.1647
Nasuella olivacea Bayesian p-value: 0.5473
Odocoileus ustus Bayesian p-value: 0.1207
Panthera onca Bayesian p-value: 0.5573
Pecari tajacu Bayesian p-value: 0.3853
Pudu mephistophiles Bayesian p-value: 0.2153
Puma concolor Bayesian p-value: 0.3407
Tapirus pinchaque Bayesian p-value: 0.392
Tayassu pecari Bayesian p-value: 0.426
Tremarctos ornatus Bayesian p-value: 0.546
Fit statistic:  freeman-tukey 
Code
summary(ppc.out.sp)

Call:
ppcOcc(object = out.sp, fit.stat = "freeman-tukey", group = 1)

Samples per Chain: 15000
Burn-in: 5000
Thinning Rate: 10
Number of Chains: 3
Total Posterior Samples: 3000

----------------------------------------
    Community Level
----------------------------------------
Bayesian p-value:  0.3915 

----------------------------------------
    Species Level
----------------------------------------
Cuniculus paca Bayesian p-value: 0.4607
Cuniculus taczanowskii Bayesian p-value: 0.392
Dasyprocta fuliginosa Bayesian p-value: 0.3647
Dasypus novemcinctus Bayesian p-value: 0.3293
Eira barbara Bayesian p-value: 0.591
Herpailurus yagouaroundi Bayesian p-value: 0.3857
Leopardus pardalis Bayesian p-value: 0.321
Leopardus tigrinus Bayesian p-value: 0.3837
Leopardus wiedii Bayesian p-value: 0.4993
Mazama murelia Bayesian p-value: 0.2587
Mazama rufina Bayesian p-value: 0.4213
Mazama zamora Bayesian p-value: 0.171
Nasuella olivacea Bayesian p-value: 0.5357
Odocoileus ustus Bayesian p-value: 0.123
Panthera onca Bayesian p-value: 0.628
Pecari tajacu Bayesian p-value: 0.3683
Pudu mephistophiles Bayesian p-value: 0.245
Puma concolor Bayesian p-value: 0.305
Tapirus pinchaque Bayesian p-value: 0.419
Tayassu pecari Bayesian p-value: 0.4333
Tremarctos ornatus Bayesian p-value: 0.586
Fit statistic:  freeman-tukey 
Important

A Bayesian p-value that around 0.5 indicates adequate model fit, while values less than 0.1 or greater than 0.9 suggest our model does not fit the data well.

Fit plot

Code
#### fit plot
ppc.df <- data.frame(fit = ppc.out.sp$fit.y, 
                     fit.rep = ppc.out.sp$fit.y.rep, 
                     color = 'lightskyblue1')

ppc.df$color[ppc.df$fit.rep.1 > ppc.df$fit.1] <- 'lightsalmon'
plot(ppc.df$fit.1, ppc.df$fit.rep.1, bg = ppc.df$color, pch = 21, 
     ylab = 'Fit', xlab = 'True')
lines(ppc.df$fit.1, ppc.df$fit.1, col = 'black')

The most symmetrical, better fit!

The most symmetrical, better fit!

Model comparison

Code
# 4. Model comparison -----------------------------------------------------
# Compute Widely Applicable Information Criterion (WAIC)
# Lower values indicate better model fit. 
waicOcc(out.null)
      elpd         pD       WAIC 
-932.33724   75.54766 2015.76979 
Code
waicOcc(out.lfMs)
     elpd        pD      WAIC 
-932.8250   75.5039 2016.6579 
Code
waicOcc(out.sp)
     elpd        pD      WAIC 
-796.7950  150.4456 1894.4812 
Code
waicOcc(out.sp.cat)
    elpd       pD     WAIC 
-796.043  151.276 1894.638 

Model comparison as table

Code
# Here we summarize the spatial factor loadings
# summary(out.sp$lambda.samples)

# Resultados --------------------------------------------------------------
# Extraemos lo tabla de valores estimados
modresult <- cbind(as.data.frame(waicOcc(out.null)),
                  as.data.frame(waicOcc(out.sp)),
                  as.data.frame(waicOcc(out.lfMs)),
                  as.data.frame(waicOcc(out.sp.cat))
                  #as.data.frame(waicOcc(out.sp.gaus))
                  )
# View(modresult)
modresult_sorted <- as.data.frame(t(modresult)) |> 
  arrange(WAIC) # sort by
  
DT::datatable(modresult_sorted)
Important

Lower values in WAIC indicate better model fit.

WAIC is the Widely Applicable Information Criterion (Watanabe 2010).

Posterior Summary

Code
# 5. Posterior summaries --------------------------------------------------
# Concise summary of main parameter estimates
summary(out.sp, level = 'community')

Call:
sfMsPGOcc(occ.formula = ~scale(elev) + scale(border_dist) + scale(FLII), 
    det.formula = ~scale(effort), data = data_list, cov.model = "exponential", 
    NNGP = TRUE, n.neighbors = 15, n.factors = 5, n.batch = 600, 
    batch.length = 25, n.omp.threads = 6, n.report = 1000, n.burn = 5000, 
    n.thin = 10, n.chains = 3)

Samples per Chain: 15000
Burn-in: 5000
Thinning Rate: 10
Number of Chains: 3
Total Posterior Samples: 3000
Run Time (min): 6.9495

----------------------------------------
    Community Level
----------------------------------------
Occurrence Means (logit scale): 
                      Mean     SD    2.5%     50%   97.5%   Rhat  ESS
(Intercept)        -4.2734 0.4812 -5.2147 -4.2802 -3.3035 1.0006  753
scale(elev)        -0.5186 0.3423 -1.2370 -0.5120  0.1291 1.0335 1185
scale(border_dist) -0.1365 0.3609 -0.8594 -0.1272  0.5906 1.0020 1010
scale(FLII)         0.5212 0.2889  0.0033  0.5042  1.1245 1.0066  818

Occurrence Variances (logit scale): 
                     Mean     SD   2.5%    50%  97.5%   Rhat ESS
(Intercept)        2.3939 1.4881 0.5365 2.0585 6.1202 1.0204 588
scale(elev)        0.6965 0.6052 0.0652 0.5374 2.2385 1.0076 905
scale(border_dist) 0.7822 0.7313 0.0637 0.5703 2.7132 1.0320 551
scale(FLII)        0.5004 0.4046 0.0673 0.3947 1.5953 1.0040 971

Detection Means (logit scale): 
                 Mean     SD    2.5%     50%   97.5%   Rhat  ESS
(Intercept)   -1.4654 0.2359 -1.9814 -1.4540 -1.0407 1.0058 1349
scale(effort)  0.4056 0.1584  0.1303  0.3943  0.7464 1.0061 2187

Detection Variances (logit scale): 
                Mean     SD   2.5%    50%  97.5%   Rhat  ESS
(Intercept)   0.6756 0.4459 0.1623 0.5772 1.8078 1.0332  714
scale(effort) 0.1806 0.1478 0.0347 0.1377 0.5739 1.0054 1902

----------------------------------------
    Spatial Covariance
----------------------------------------
        Mean     SD  2.5%    50%  97.5%   Rhat ESS
phi-1 0.0004 0.0031 0e+00 0.0001 0.0004 2.3686  66
phi-2 0.0161 0.0128 1e-04 0.0149 0.0394 1.0610  59
phi-3 0.0173 0.0127 2e-04 0.0163 0.0396 1.0460 144
phi-4 0.0153 0.0132 1e-04 0.0127 0.0396 1.1766 123
phi-5 0.0179 0.0126 3e-04 0.0169 0.0396 1.0119 470
Code
summary(out.sp, level = 'species')

Call:
sfMsPGOcc(occ.formula = ~scale(elev) + scale(border_dist) + scale(FLII), 
    det.formula = ~scale(effort), data = data_list, cov.model = "exponential", 
    NNGP = TRUE, n.neighbors = 15, n.factors = 5, n.batch = 600, 
    batch.length = 25, n.omp.threads = 6, n.report = 1000, n.burn = 5000, 
    n.thin = 10, n.chains = 3)

Samples per Chain: 15000
Burn-in: 5000
Thinning Rate: 10
Number of Chains: 3
Total Posterior Samples: 3000
Run Time (min): 6.9495

----------------------------------------
    Species Level
----------------------------------------
Occurrence (logit scale): 
                                               Mean     SD    2.5%     50%
(Intercept)-Cuniculus paca                  -4.0982 0.9308 -6.0602 -4.0553
(Intercept)-Cuniculus taczanowskii          -4.4070 0.9564 -6.3593 -4.3435
(Intercept)-Dasyprocta fuliginosa           -4.4496 1.0229 -6.6285 -4.3793
(Intercept)-Dasypus novemcinctus            -3.8352 1.0725 -6.0935 -3.8153
(Intercept)-Eira barbara                    -4.8126 1.1735 -7.2858 -4.7901
(Intercept)-Herpailurus yagouaroundi        -5.3698 1.1946 -7.8470 -5.3177
(Intercept)-Leopardus pardalis              -4.7880 1.0940 -7.0595 -4.7223
(Intercept)-Leopardus tigrinus              -4.5643 1.0440 -6.7129 -4.5231
(Intercept)-Leopardus wiedii                -4.9365 1.1594 -7.3856 -4.8889
(Intercept)-Mazama murelia                  -5.6531 1.1715 -8.2255 -5.5217
(Intercept)-Mazama rufina                   -3.8777 0.8840 -5.7215 -3.8380
(Intercept)-Mazama zamora                   -5.7872 1.1363 -8.2608 -5.6472
(Intercept)-Nasuella olivacea               -4.7138 1.0896 -6.8827 -4.6807
(Intercept)-Odocoileus ustus                -3.6538 1.0328 -5.8055 -3.6144
(Intercept)-Panthera onca                   -4.6757 1.1882 -7.1950 -4.6278
(Intercept)-Pecari tajacu                   -4.2269 1.0412 -6.3930 -4.1835
(Intercept)-Pudu mephistophiles             -5.1072 0.9861 -7.1885 -5.0462
(Intercept)-Puma concolor                   -4.0413 0.9995 -6.1533 -4.0139
(Intercept)-Tapirus pinchaque               -4.3577 0.9933 -6.4982 -4.3137
(Intercept)-Tayassu pecari                  -5.3587 1.2279 -8.0009 -5.2679
(Intercept)-Tremarctos ornatus              -0.7175 1.0333 -2.9544 -0.6769
scale(elev)-Cuniculus paca                  -1.2325 0.6974 -2.7615 -1.1486
scale(elev)-Cuniculus taczanowskii           0.1226 0.7583 -1.1986  0.0472
scale(elev)-Dasyprocta fuliginosa           -1.0499 0.7419 -2.7087 -0.9678
scale(elev)-Dasypus novemcinctus            -0.7247 0.6507 -2.0216 -0.7034
scale(elev)-Eira barbara                    -0.7628 0.7465 -2.3808 -0.7132
scale(elev)-Herpailurus yagouaroundi        -0.5731 0.7504 -2.0896 -0.5464
scale(elev)-Leopardus pardalis              -0.9023 0.7467 -2.5890 -0.8387
scale(elev)-Leopardus tigrinus              -1.1060 0.7358 -2.6784 -1.0192
scale(elev)-Leopardus wiedii                 0.3599 0.8617 -1.0616  0.2690
scale(elev)-Mazama murelia                  -0.5812 0.7166 -2.0925 -0.5540
scale(elev)-Mazama rufina                   -0.3177 0.6056 -1.4886 -0.3362
scale(elev)-Mazama zamora                   -0.5591 0.7110 -2.0690 -0.5313
scale(elev)-Nasuella olivacea               -0.4720 0.6841 -1.8643 -0.4650
scale(elev)-Odocoileus ustus                -0.2134 0.5861 -1.3283 -0.2212
scale(elev)-Panthera onca                   -0.8989 0.7732 -2.6195 -0.8411
scale(elev)-Pecari tajacu                   -0.9979 0.6791 -2.5060 -0.9318
scale(elev)-Pudu mephistophiles             -0.4399 0.6655 -1.7537 -0.4422
scale(elev)-Puma concolor                   -0.0693 0.6643 -1.3147 -0.0933
scale(elev)-Tapirus pinchaque               -0.3830 0.6374 -1.6061 -0.3807
scale(elev)-Tayassu pecari                  -0.5867 0.7379 -2.1584 -0.5598
scale(elev)-Tremarctos ornatus               0.2643 0.6415 -0.9131  0.2380
scale(border_dist)-Cuniculus paca            0.7116 0.7277 -0.4709  0.6292
scale(border_dist)-Cuniculus taczanowskii   -0.7044 0.7325 -2.3481 -0.6399
scale(border_dist)-Dasyprocta fuliginosa    -0.3846 0.7497 -2.0207 -0.3350
scale(border_dist)-Dasypus novemcinctus      0.3360 0.7797 -0.9967  0.2711
scale(border_dist)-Eira barbara              0.3754 0.7974 -1.0421  0.3011
scale(border_dist)-Herpailurus yagouaroundi -0.1978 0.7919 -1.8605 -0.1715
scale(border_dist)-Leopardus pardalis        0.2584 0.7522 -1.1085  0.1880
scale(border_dist)-Leopardus tigrinus       -0.1811 0.7252 -1.6439 -0.1669
scale(border_dist)-Leopardus wiedii         -0.1706 0.7912 -1.8097 -0.1589
scale(border_dist)-Mazama murelia           -0.1384 0.7437 -1.6593 -0.1214
scale(border_dist)-Mazama rufina             0.1254 0.6688 -1.2228  0.1191
scale(border_dist)-Mazama zamora            -0.2273 0.7416 -1.7408 -0.2057
scale(border_dist)-Nasuella olivacea        -0.7405 0.8019 -2.5373 -0.6521
scale(border_dist)-Odocoileus ustus          0.1729 0.6340 -1.0421  0.1649
scale(border_dist)-Panthera onca            -0.2826 0.8008 -2.0133 -0.2623
scale(border_dist)-Pecari tajacu            -0.0404 0.6931 -1.3799 -0.0558
scale(border_dist)-Pudu mephistophiles      -0.6651 0.7507 -2.3363 -0.5681
scale(border_dist)-Puma concolor            -0.9093 0.7992 -2.6261 -0.8218
scale(border_dist)-Tapirus pinchaque        -0.7660 0.7903 -2.5496 -0.6852
scale(border_dist)-Tayassu pecari           -0.0904 0.8051 -1.7209 -0.0854
scale(border_dist)-Tremarctos ornatus        0.5709 0.7289 -0.6729  0.5066
scale(FLII)-Cuniculus paca                   0.8878 0.6547 -0.2178  0.8073
scale(FLII)-Cuniculus taczanowskii           1.1839 0.6465  0.1484  1.1056
scale(FLII)-Dasyprocta fuliginosa            0.5141 0.6493 -0.6857  0.4901
scale(FLII)-Dasypus novemcinctus             0.7583 0.6833 -0.4682  0.6987
scale(FLII)-Eira barbara                     0.4386 0.6719 -0.9099  0.4249
scale(FLII)-Herpailurus yagouaroundi         0.2247 0.6869 -1.2840  0.2612
scale(FLII)-Leopardus pardalis               0.6853 0.6712 -0.5030  0.6342
scale(FLII)-Leopardus tigrinus               0.3452 0.5618 -0.7781  0.3465
scale(FLII)-Leopardus wiedii                 0.6414 0.6942 -0.5929  0.5896
scale(FLII)-Mazama murelia                   0.4834 0.6608 -0.8192  0.4664
scale(FLII)-Mazama rufina                    0.3880 0.5209 -0.6272  0.3855
scale(FLII)-Mazama zamora                    0.5160 0.6533 -0.7559  0.5014
scale(FLII)-Nasuella olivacea                0.6334 0.5518 -0.3828  0.6050
scale(FLII)-Odocoileus ustus                -0.3873 0.5162 -1.4654 -0.3704
scale(FLII)-Panthera onca                    0.5050 0.6751 -0.7871  0.4800
scale(FLII)-Pecari tajacu                    0.7489 0.6978 -0.4184  0.6879
scale(FLII)-Pudu mephistophiles              0.7042 0.5018 -0.1961  0.6612
scale(FLII)-Puma concolor                   -0.1850 0.4923 -1.2204 -0.1553
scale(FLII)-Tapirus pinchaque                0.7603 0.4980 -0.1079  0.7334
scale(FLII)-Tayassu pecari                   0.5467 0.6639 -0.7406  0.5005
scale(FLII)-Tremarctos ornatus               0.5082 0.5000 -0.4086  0.4766
                                              97.5%   Rhat  ESS
(Intercept)-Cuniculus paca                  -2.3973 1.0125  844
(Intercept)-Cuniculus taczanowskii          -2.6598 1.0043  909
(Intercept)-Dasyprocta fuliginosa           -2.6026 1.0042  855
(Intercept)-Dasypus novemcinctus            -1.7788 1.0075  686
(Intercept)-Eira barbara                    -2.5856 1.0016  949
(Intercept)-Herpailurus yagouaroundi        -3.1610 1.0052 1009
(Intercept)-Leopardus pardalis              -2.7920 1.0065 1136
(Intercept)-Leopardus tigrinus              -2.5808 1.0060  749
(Intercept)-Leopardus wiedii                -2.7957 1.0117  791
(Intercept)-Mazama murelia                  -3.6961 1.0064  869
(Intercept)-Mazama rufina                   -2.2974 1.0053 1035
(Intercept)-Mazama zamora                   -3.9164 1.0203  930
(Intercept)-Nasuella olivacea               -2.6207 1.0039  905
(Intercept)-Odocoileus ustus                -1.8182 1.0153  366
(Intercept)-Panthera onca                   -2.5494 1.0016  836
(Intercept)-Pecari tajacu                   -2.3050 1.0034  871
(Intercept)-Pudu mephistophiles             -3.3761 1.0076 1122
(Intercept)-Puma concolor                   -2.1961 1.0180  791
(Intercept)-Tapirus pinchaque               -2.5968 1.0006  920
(Intercept)-Tayassu pecari                  -3.1295 1.0052  752
(Intercept)-Tremarctos ornatus               1.2789 1.0777  394
scale(elev)-Cuniculus paca                  -0.0966 1.0247 1221
scale(elev)-Cuniculus taczanowskii           1.8188 1.0069 1610
scale(elev)-Dasyprocta fuliginosa            0.2850 1.0145 1404
scale(elev)-Dasypus novemcinctus             0.5264 1.0128 1774
scale(elev)-Eira barbara                     0.5849 1.0072 1704
scale(elev)-Herpailurus yagouaroundi         0.9392 1.0330 1778
scale(elev)-Leopardus pardalis               0.4266 1.0177 1411
scale(elev)-Leopardus tigrinus               0.1354 1.0132 1568
scale(elev)-Leopardus wiedii                 2.2834 1.0011 1199
scale(elev)-Mazama murelia                   0.7919 1.0257 2033
scale(elev)-Mazama rufina                    0.8803 1.0044 1485
scale(elev)-Mazama zamora                    0.8254 1.0106 2034
scale(elev)-Nasuella olivacea                0.8827 1.0115 2260
scale(elev)-Odocoileus ustus                 1.0063 1.0056 1546
scale(elev)-Panthera onca                    0.5007 1.0236 1396
scale(elev)-Pecari tajacu                    0.1973 1.0098 1541
scale(elev)-Pudu mephistophiles              0.9353 1.0116 1961
scale(elev)-Puma concolor                    1.3442 1.0029 1897
scale(elev)-Tapirus pinchaque                0.9169 1.0094 1995
scale(elev)-Tayassu pecari                   0.7844 1.0185 1518
scale(elev)-Tremarctos ornatus               1.6449 1.0003 1260
scale(border_dist)-Cuniculus paca            2.3142 1.0192  918
scale(border_dist)-Cuniculus taczanowskii    0.5398 1.0099  835
scale(border_dist)-Dasyprocta fuliginosa     0.9821 1.0030 1385
scale(border_dist)-Dasypus novemcinctus      2.0693 1.0149 1189
scale(border_dist)-Eira barbara              2.1964 1.0048 1361
scale(border_dist)-Herpailurus yagouaroundi  1.3161 1.0074 1979
scale(border_dist)-Leopardus pardalis        1.8864 1.0091 1518
scale(border_dist)-Leopardus tigrinus        1.2670 1.0102 1579
scale(border_dist)-Leopardus wiedii          1.4444 1.0013 1841
scale(border_dist)-Mazama murelia            1.3249 1.0042 1688
scale(border_dist)-Mazama rufina             1.4548 1.0026 1499
scale(border_dist)-Mazama zamora             1.1845 1.0010 2048
scale(border_dist)-Nasuella olivacea         0.6466 1.0215  712
scale(border_dist)-Odocoileus ustus          1.4785 1.0126 1765
scale(border_dist)-Panthera onca             1.3197 1.0021 1417
scale(border_dist)-Pecari tajacu             1.4291 1.0038 1676
scale(border_dist)-Pudu mephistophiles       0.5706 1.0044  848
scale(border_dist)-Puma concolor             0.4342 1.0193  891
scale(border_dist)-Tapirus pinchaque         0.5635 1.0128  582
scale(border_dist)-Tayassu pecari            1.5668 1.0038 1791
scale(border_dist)-Tremarctos ornatus        2.1304 1.0180  712
scale(FLII)-Cuniculus paca                   2.3511 1.0067 1244
scale(FLII)-Cuniculus taczanowskii           2.6829 1.0059 1063
scale(FLII)-Dasyprocta fuliginosa            1.8947 1.0020 2031
scale(FLII)-Dasypus novemcinctus             2.3114 1.0006 1585
scale(FLII)-Eira barbara                     1.8436 1.0030 1886
scale(FLII)-Herpailurus yagouaroundi         1.5243 1.0030 2015
scale(FLII)-Leopardus pardalis               2.1510 1.0037 1703
scale(FLII)-Leopardus tigrinus               1.4972 1.0041 1478
scale(FLII)-Leopardus wiedii                 2.1298 1.0048 1552
scale(FLII)-Mazama murelia                   1.9045 1.0044 2126
scale(FLII)-Mazama rufina                    1.4430 1.0035 1984
scale(FLII)-Mazama zamora                    1.8657 1.0039 1862
scale(FLII)-Nasuella olivacea                1.7966 1.0038 1966
scale(FLII)-Odocoileus ustus                 0.5796 1.0008 1262
scale(FLII)-Panthera onca                    1.9370 1.0121 1969
scale(FLII)-Pecari tajacu                    2.3174 1.0011 1401
scale(FLII)-Pudu mephistophiles              1.7562 1.0070 1478
scale(FLII)-Puma concolor                    0.7157 1.0038 2120
scale(FLII)-Tapirus pinchaque                1.8256 1.0041 1455
scale(FLII)-Tayassu pecari                   1.9851 1.0012 1486
scale(FLII)-Tremarctos ornatus               1.5779 1.0018 1107

Detection (logit scale): 
                                          Mean     SD    2.5%     50%   97.5%
(Intercept)-Cuniculus paca             -0.6424 0.2900 -1.2149 -0.6438 -0.0720
(Intercept)-Cuniculus taczanowskii     -1.7702 0.4490 -2.7464 -1.7377 -0.9548
(Intercept)-Dasyprocta fuliginosa      -1.2893 0.4466 -2.1876 -1.2715 -0.4573
(Intercept)-Dasypus novemcinctus       -0.7070 0.2595 -1.1935 -0.7135 -0.2144
(Intercept)-Eira barbara               -2.1585 0.6826 -3.6464 -2.1322 -0.9573
(Intercept)-Herpailurus yagouaroundi   -1.9464 0.8436 -3.8952 -1.8817 -0.4649
(Intercept)-Leopardus pardalis         -1.6179 0.5637 -2.7746 -1.5921 -0.5733
(Intercept)-Leopardus tigrinus         -2.1589 0.5865 -3.4348 -2.1102 -1.1716
(Intercept)-Leopardus wiedii           -1.9765 0.7659 -3.6908 -1.9062 -0.6952
(Intercept)-Mazama murelia             -1.0338 0.7232 -2.4749 -1.0383  0.4868
(Intercept)-Mazama rufina              -1.1736 0.3100 -1.7987 -1.1738 -0.5846
(Intercept)-Mazama zamora              -0.4904 0.7480 -1.9174 -0.5091  1.0138
(Intercept)-Nasuella olivacea          -2.1143 0.5633 -3.3476 -2.0632 -1.1497
(Intercept)-Odocoileus ustus           -1.4062 0.2018 -1.8301 -1.4017 -1.0214
(Intercept)-Panthera onca              -2.0800 0.6023 -3.3270 -2.0604 -0.9661
(Intercept)-Pecari tajacu              -0.4912 0.2748 -1.0344 -0.4862  0.0380
(Intercept)-Pudu mephistophiles        -1.0344 0.3724 -1.7867 -1.0305 -0.3513
(Intercept)-Puma concolor              -1.6474 0.3571 -2.3843 -1.6292 -1.0082
(Intercept)-Tapirus pinchaque          -1.3769 0.2649 -1.9087 -1.3697 -0.8701
(Intercept)-Tayassu pecari             -2.0516 0.8308 -3.8600 -1.9677 -0.6113
(Intercept)-Tremarctos ornatus         -2.0407 0.2550 -2.5558 -2.0373 -1.5709
scale(effort)-Cuniculus paca            0.5941 0.3222  0.0704  0.5559  1.3369
scale(effort)-Cuniculus taczanowskii    0.2196 0.3255 -0.4109  0.2160  0.8732
scale(effort)-Dasyprocta fuliginosa     0.4998 0.3619 -0.1389  0.4689  1.3262
scale(effort)-Dasypus novemcinctus      0.1483 0.2112 -0.2477  0.1373  0.5915
scale(effort)-Eira barbara              0.4599 0.3983 -0.2232  0.4266  1.3920
scale(effort)-Herpailurus yagouaroundi  0.4374 0.4310 -0.3501  0.4034  1.4110
scale(effort)-Leopardus pardalis        0.4425 0.3436 -0.1584  0.4214  1.2217
scale(effort)-Leopardus tigrinus        0.4386 0.3531 -0.1774  0.4105  1.2368
scale(effort)-Leopardus wiedii          0.4079 0.4269 -0.3714  0.3843  1.3061
scale(effort)-Mazama murelia            0.5083 0.3991 -0.1755  0.4747  1.4221
scale(effort)-Mazama rufina             0.6507 0.3658  0.0723  0.5947  1.4992
scale(effort)-Mazama zamora             0.3601 0.4379 -0.5240  0.3640  1.2397
scale(effort)-Nasuella olivacea         0.1520 0.3335 -0.4905  0.1504  0.8114
scale(effort)-Odocoileus ustus          0.6758 0.3314  0.1534  0.6451  1.4367
scale(effort)-Panthera onca             0.5287 0.4281 -0.2113  0.4899  1.4977
scale(effort)-Pecari tajacu             0.5210 0.2782  0.0491  0.4976  1.1729
scale(effort)-Pudu mephistophiles      -0.1184 0.3198 -0.7795 -0.1077  0.4649
scale(effort)-Puma concolor             0.1284 0.2488 -0.3518  0.1265  0.6261
scale(effort)-Tapirus pinchaque         0.6220 0.3180  0.0972  0.5827  1.3423
scale(effort)-Tayassu pecari            0.4451 0.4056 -0.2844  0.4191  1.3418
scale(effort)-Tremarctos ornatus        0.3831 0.2472 -0.0533  0.3667  0.9047
                                         Rhat  ESS
(Intercept)-Cuniculus paca             1.0008 2714
(Intercept)-Cuniculus taczanowskii     1.0033 2353
(Intercept)-Dasyprocta fuliginosa      1.0060 2420
(Intercept)-Dasypus novemcinctus       1.0005 2825
(Intercept)-Eira barbara               1.0066 1027
(Intercept)-Herpailurus yagouaroundi   1.0081 1070
(Intercept)-Leopardus pardalis         0.9998 1307
(Intercept)-Leopardus tigrinus         1.0018 1205
(Intercept)-Leopardus wiedii           1.0209  768
(Intercept)-Mazama murelia             1.0020 2684
(Intercept)-Mazama rufina              1.0000 2845
(Intercept)-Mazama zamora              1.0168 2676
(Intercept)-Nasuella olivacea          1.0076 1384
(Intercept)-Odocoileus ustus           1.0031 2611
(Intercept)-Panthera onca              1.0077 1229
(Intercept)-Pecari tajacu              1.0058 3000
(Intercept)-Pudu mephistophiles        1.0029 2663
(Intercept)-Puma concolor              1.0005 2224
(Intercept)-Tapirus pinchaque          1.0006 3000
(Intercept)-Tayassu pecari             1.0219  992
(Intercept)-Tremarctos ornatus         1.0070 1312
scale(effort)-Cuniculus paca           1.0008 2461
scale(effort)-Cuniculus taczanowskii   1.0027 2829
scale(effort)-Dasyprocta fuliginosa    1.0003 2675
scale(effort)-Dasypus novemcinctus     1.0040 3186
scale(effort)-Eira barbara             1.0033 2699
scale(effort)-Herpailurus yagouaroundi 1.0003 2833
scale(effort)-Leopardus pardalis       1.0031 2791
scale(effort)-Leopardus tigrinus       1.0018 3000
scale(effort)-Leopardus wiedii         1.0106 2729
scale(effort)-Mazama murelia           1.0019 2623
scale(effort)-Mazama rufina            1.0084 1972
scale(effort)-Mazama zamora            1.0015 3000
scale(effort)-Nasuella olivacea        1.0035 3000
scale(effort)-Odocoileus ustus         1.0015 2538
scale(effort)-Panthera onca            1.0000 3000
scale(effort)-Pecari tajacu            1.0136 2753
scale(effort)-Pudu mephistophiles      1.0041 2594
scale(effort)-Puma concolor            1.0033 2825
scale(effort)-Tapirus pinchaque        1.0017 2478
scale(effort)-Tayassu pecari           1.0139 2725
scale(effort)-Tremarctos ornatus       1.0060 2812

----------------------------------------
    Spatial Covariance
----------------------------------------
        Mean     SD  2.5%    50%  97.5%   Rhat ESS
phi-1 0.0004 0.0031 0e+00 0.0001 0.0004 2.3686  66
phi-2 0.0161 0.0128 1e-04 0.0149 0.0394 1.0610  59
phi-3 0.0173 0.0127 2e-04 0.0163 0.0396 1.0460 144
phi-4 0.0153 0.0132 1e-04 0.0127 0.0396 1.1766 123
phi-5 0.0179 0.0126 3e-04 0.0169 0.0396 1.0119 470
Code
summary(out.sp, level = 'both')

Call:
sfMsPGOcc(occ.formula = ~scale(elev) + scale(border_dist) + scale(FLII), 
    det.formula = ~scale(effort), data = data_list, cov.model = "exponential", 
    NNGP = TRUE, n.neighbors = 15, n.factors = 5, n.batch = 600, 
    batch.length = 25, n.omp.threads = 6, n.report = 1000, n.burn = 5000, 
    n.thin = 10, n.chains = 3)

Samples per Chain: 15000
Burn-in: 5000
Thinning Rate: 10
Number of Chains: 3
Total Posterior Samples: 3000
Run Time (min): 6.9495

----------------------------------------
    Community Level
----------------------------------------
Occurrence Means (logit scale): 
                      Mean     SD    2.5%     50%   97.5%   Rhat  ESS
(Intercept)        -4.2734 0.4812 -5.2147 -4.2802 -3.3035 1.0006  753
scale(elev)        -0.5186 0.3423 -1.2370 -0.5120  0.1291 1.0335 1185
scale(border_dist) -0.1365 0.3609 -0.8594 -0.1272  0.5906 1.0020 1010
scale(FLII)         0.5212 0.2889  0.0033  0.5042  1.1245 1.0066  818

Occurrence Variances (logit scale): 
                     Mean     SD   2.5%    50%  97.5%   Rhat ESS
(Intercept)        2.3939 1.4881 0.5365 2.0585 6.1202 1.0204 588
scale(elev)        0.6965 0.6052 0.0652 0.5374 2.2385 1.0076 905
scale(border_dist) 0.7822 0.7313 0.0637 0.5703 2.7132 1.0320 551
scale(FLII)        0.5004 0.4046 0.0673 0.3947 1.5953 1.0040 971

Detection Means (logit scale): 
                 Mean     SD    2.5%     50%   97.5%   Rhat  ESS
(Intercept)   -1.4654 0.2359 -1.9814 -1.4540 -1.0407 1.0058 1349
scale(effort)  0.4056 0.1584  0.1303  0.3943  0.7464 1.0061 2187

Detection Variances (logit scale): 
                Mean     SD   2.5%    50%  97.5%   Rhat  ESS
(Intercept)   0.6756 0.4459 0.1623 0.5772 1.8078 1.0332  714
scale(effort) 0.1806 0.1478 0.0347 0.1377 0.5739 1.0054 1902

----------------------------------------
    Species Level
----------------------------------------
Occurrence (logit scale): 
                                               Mean     SD    2.5%     50%
(Intercept)-Cuniculus paca                  -4.0982 0.9308 -6.0602 -4.0553
(Intercept)-Cuniculus taczanowskii          -4.4070 0.9564 -6.3593 -4.3435
(Intercept)-Dasyprocta fuliginosa           -4.4496 1.0229 -6.6285 -4.3793
(Intercept)-Dasypus novemcinctus            -3.8352 1.0725 -6.0935 -3.8153
(Intercept)-Eira barbara                    -4.8126 1.1735 -7.2858 -4.7901
(Intercept)-Herpailurus yagouaroundi        -5.3698 1.1946 -7.8470 -5.3177
(Intercept)-Leopardus pardalis              -4.7880 1.0940 -7.0595 -4.7223
(Intercept)-Leopardus tigrinus              -4.5643 1.0440 -6.7129 -4.5231
(Intercept)-Leopardus wiedii                -4.9365 1.1594 -7.3856 -4.8889
(Intercept)-Mazama murelia                  -5.6531 1.1715 -8.2255 -5.5217
(Intercept)-Mazama rufina                   -3.8777 0.8840 -5.7215 -3.8380
(Intercept)-Mazama zamora                   -5.7872 1.1363 -8.2608 -5.6472
(Intercept)-Nasuella olivacea               -4.7138 1.0896 -6.8827 -4.6807
(Intercept)-Odocoileus ustus                -3.6538 1.0328 -5.8055 -3.6144
(Intercept)-Panthera onca                   -4.6757 1.1882 -7.1950 -4.6278
(Intercept)-Pecari tajacu                   -4.2269 1.0412 -6.3930 -4.1835
(Intercept)-Pudu mephistophiles             -5.1072 0.9861 -7.1885 -5.0462
(Intercept)-Puma concolor                   -4.0413 0.9995 -6.1533 -4.0139
(Intercept)-Tapirus pinchaque               -4.3577 0.9933 -6.4982 -4.3137
(Intercept)-Tayassu pecari                  -5.3587 1.2279 -8.0009 -5.2679
(Intercept)-Tremarctos ornatus              -0.7175 1.0333 -2.9544 -0.6769
scale(elev)-Cuniculus paca                  -1.2325 0.6974 -2.7615 -1.1486
scale(elev)-Cuniculus taczanowskii           0.1226 0.7583 -1.1986  0.0472
scale(elev)-Dasyprocta fuliginosa           -1.0499 0.7419 -2.7087 -0.9678
scale(elev)-Dasypus novemcinctus            -0.7247 0.6507 -2.0216 -0.7034
scale(elev)-Eira barbara                    -0.7628 0.7465 -2.3808 -0.7132
scale(elev)-Herpailurus yagouaroundi        -0.5731 0.7504 -2.0896 -0.5464
scale(elev)-Leopardus pardalis              -0.9023 0.7467 -2.5890 -0.8387
scale(elev)-Leopardus tigrinus              -1.1060 0.7358 -2.6784 -1.0192
scale(elev)-Leopardus wiedii                 0.3599 0.8617 -1.0616  0.2690
scale(elev)-Mazama murelia                  -0.5812 0.7166 -2.0925 -0.5540
scale(elev)-Mazama rufina                   -0.3177 0.6056 -1.4886 -0.3362
scale(elev)-Mazama zamora                   -0.5591 0.7110 -2.0690 -0.5313
scale(elev)-Nasuella olivacea               -0.4720 0.6841 -1.8643 -0.4650
scale(elev)-Odocoileus ustus                -0.2134 0.5861 -1.3283 -0.2212
scale(elev)-Panthera onca                   -0.8989 0.7732 -2.6195 -0.8411
scale(elev)-Pecari tajacu                   -0.9979 0.6791 -2.5060 -0.9318
scale(elev)-Pudu mephistophiles             -0.4399 0.6655 -1.7537 -0.4422
scale(elev)-Puma concolor                   -0.0693 0.6643 -1.3147 -0.0933
scale(elev)-Tapirus pinchaque               -0.3830 0.6374 -1.6061 -0.3807
scale(elev)-Tayassu pecari                  -0.5867 0.7379 -2.1584 -0.5598
scale(elev)-Tremarctos ornatus               0.2643 0.6415 -0.9131  0.2380
scale(border_dist)-Cuniculus paca            0.7116 0.7277 -0.4709  0.6292
scale(border_dist)-Cuniculus taczanowskii   -0.7044 0.7325 -2.3481 -0.6399
scale(border_dist)-Dasyprocta fuliginosa    -0.3846 0.7497 -2.0207 -0.3350
scale(border_dist)-Dasypus novemcinctus      0.3360 0.7797 -0.9967  0.2711
scale(border_dist)-Eira barbara              0.3754 0.7974 -1.0421  0.3011
scale(border_dist)-Herpailurus yagouaroundi -0.1978 0.7919 -1.8605 -0.1715
scale(border_dist)-Leopardus pardalis        0.2584 0.7522 -1.1085  0.1880
scale(border_dist)-Leopardus tigrinus       -0.1811 0.7252 -1.6439 -0.1669
scale(border_dist)-Leopardus wiedii         -0.1706 0.7912 -1.8097 -0.1589
scale(border_dist)-Mazama murelia           -0.1384 0.7437 -1.6593 -0.1214
scale(border_dist)-Mazama rufina             0.1254 0.6688 -1.2228  0.1191
scale(border_dist)-Mazama zamora            -0.2273 0.7416 -1.7408 -0.2057
scale(border_dist)-Nasuella olivacea        -0.7405 0.8019 -2.5373 -0.6521
scale(border_dist)-Odocoileus ustus          0.1729 0.6340 -1.0421  0.1649
scale(border_dist)-Panthera onca            -0.2826 0.8008 -2.0133 -0.2623
scale(border_dist)-Pecari tajacu            -0.0404 0.6931 -1.3799 -0.0558
scale(border_dist)-Pudu mephistophiles      -0.6651 0.7507 -2.3363 -0.5681
scale(border_dist)-Puma concolor            -0.9093 0.7992 -2.6261 -0.8218
scale(border_dist)-Tapirus pinchaque        -0.7660 0.7903 -2.5496 -0.6852
scale(border_dist)-Tayassu pecari           -0.0904 0.8051 -1.7209 -0.0854
scale(border_dist)-Tremarctos ornatus        0.5709 0.7289 -0.6729  0.5066
scale(FLII)-Cuniculus paca                   0.8878 0.6547 -0.2178  0.8073
scale(FLII)-Cuniculus taczanowskii           1.1839 0.6465  0.1484  1.1056
scale(FLII)-Dasyprocta fuliginosa            0.5141 0.6493 -0.6857  0.4901
scale(FLII)-Dasypus novemcinctus             0.7583 0.6833 -0.4682  0.6987
scale(FLII)-Eira barbara                     0.4386 0.6719 -0.9099  0.4249
scale(FLII)-Herpailurus yagouaroundi         0.2247 0.6869 -1.2840  0.2612
scale(FLII)-Leopardus pardalis               0.6853 0.6712 -0.5030  0.6342
scale(FLII)-Leopardus tigrinus               0.3452 0.5618 -0.7781  0.3465
scale(FLII)-Leopardus wiedii                 0.6414 0.6942 -0.5929  0.5896
scale(FLII)-Mazama murelia                   0.4834 0.6608 -0.8192  0.4664
scale(FLII)-Mazama rufina                    0.3880 0.5209 -0.6272  0.3855
scale(FLII)-Mazama zamora                    0.5160 0.6533 -0.7559  0.5014
scale(FLII)-Nasuella olivacea                0.6334 0.5518 -0.3828  0.6050
scale(FLII)-Odocoileus ustus                -0.3873 0.5162 -1.4654 -0.3704
scale(FLII)-Panthera onca                    0.5050 0.6751 -0.7871  0.4800
scale(FLII)-Pecari tajacu                    0.7489 0.6978 -0.4184  0.6879
scale(FLII)-Pudu mephistophiles              0.7042 0.5018 -0.1961  0.6612
scale(FLII)-Puma concolor                   -0.1850 0.4923 -1.2204 -0.1553
scale(FLII)-Tapirus pinchaque                0.7603 0.4980 -0.1079  0.7334
scale(FLII)-Tayassu pecari                   0.5467 0.6639 -0.7406  0.5005
scale(FLII)-Tremarctos ornatus               0.5082 0.5000 -0.4086  0.4766
                                              97.5%   Rhat  ESS
(Intercept)-Cuniculus paca                  -2.3973 1.0125  844
(Intercept)-Cuniculus taczanowskii          -2.6598 1.0043  909
(Intercept)-Dasyprocta fuliginosa           -2.6026 1.0042  855
(Intercept)-Dasypus novemcinctus            -1.7788 1.0075  686
(Intercept)-Eira barbara                    -2.5856 1.0016  949
(Intercept)-Herpailurus yagouaroundi        -3.1610 1.0052 1009
(Intercept)-Leopardus pardalis              -2.7920 1.0065 1136
(Intercept)-Leopardus tigrinus              -2.5808 1.0060  749
(Intercept)-Leopardus wiedii                -2.7957 1.0117  791
(Intercept)-Mazama murelia                  -3.6961 1.0064  869
(Intercept)-Mazama rufina                   -2.2974 1.0053 1035
(Intercept)-Mazama zamora                   -3.9164 1.0203  930
(Intercept)-Nasuella olivacea               -2.6207 1.0039  905
(Intercept)-Odocoileus ustus                -1.8182 1.0153  366
(Intercept)-Panthera onca                   -2.5494 1.0016  836
(Intercept)-Pecari tajacu                   -2.3050 1.0034  871
(Intercept)-Pudu mephistophiles             -3.3761 1.0076 1122
(Intercept)-Puma concolor                   -2.1961 1.0180  791
(Intercept)-Tapirus pinchaque               -2.5968 1.0006  920
(Intercept)-Tayassu pecari                  -3.1295 1.0052  752
(Intercept)-Tremarctos ornatus               1.2789 1.0777  394
scale(elev)-Cuniculus paca                  -0.0966 1.0247 1221
scale(elev)-Cuniculus taczanowskii           1.8188 1.0069 1610
scale(elev)-Dasyprocta fuliginosa            0.2850 1.0145 1404
scale(elev)-Dasypus novemcinctus             0.5264 1.0128 1774
scale(elev)-Eira barbara                     0.5849 1.0072 1704
scale(elev)-Herpailurus yagouaroundi         0.9392 1.0330 1778
scale(elev)-Leopardus pardalis               0.4266 1.0177 1411
scale(elev)-Leopardus tigrinus               0.1354 1.0132 1568
scale(elev)-Leopardus wiedii                 2.2834 1.0011 1199
scale(elev)-Mazama murelia                   0.7919 1.0257 2033
scale(elev)-Mazama rufina                    0.8803 1.0044 1485
scale(elev)-Mazama zamora                    0.8254 1.0106 2034
scale(elev)-Nasuella olivacea                0.8827 1.0115 2260
scale(elev)-Odocoileus ustus                 1.0063 1.0056 1546
scale(elev)-Panthera onca                    0.5007 1.0236 1396
scale(elev)-Pecari tajacu                    0.1973 1.0098 1541
scale(elev)-Pudu mephistophiles              0.9353 1.0116 1961
scale(elev)-Puma concolor                    1.3442 1.0029 1897
scale(elev)-Tapirus pinchaque                0.9169 1.0094 1995
scale(elev)-Tayassu pecari                   0.7844 1.0185 1518
scale(elev)-Tremarctos ornatus               1.6449 1.0003 1260
scale(border_dist)-Cuniculus paca            2.3142 1.0192  918
scale(border_dist)-Cuniculus taczanowskii    0.5398 1.0099  835
scale(border_dist)-Dasyprocta fuliginosa     0.9821 1.0030 1385
scale(border_dist)-Dasypus novemcinctus      2.0693 1.0149 1189
scale(border_dist)-Eira barbara              2.1964 1.0048 1361
scale(border_dist)-Herpailurus yagouaroundi  1.3161 1.0074 1979
scale(border_dist)-Leopardus pardalis        1.8864 1.0091 1518
scale(border_dist)-Leopardus tigrinus        1.2670 1.0102 1579
scale(border_dist)-Leopardus wiedii          1.4444 1.0013 1841
scale(border_dist)-Mazama murelia            1.3249 1.0042 1688
scale(border_dist)-Mazama rufina             1.4548 1.0026 1499
scale(border_dist)-Mazama zamora             1.1845 1.0010 2048
scale(border_dist)-Nasuella olivacea         0.6466 1.0215  712
scale(border_dist)-Odocoileus ustus          1.4785 1.0126 1765
scale(border_dist)-Panthera onca             1.3197 1.0021 1417
scale(border_dist)-Pecari tajacu             1.4291 1.0038 1676
scale(border_dist)-Pudu mephistophiles       0.5706 1.0044  848
scale(border_dist)-Puma concolor             0.4342 1.0193  891
scale(border_dist)-Tapirus pinchaque         0.5635 1.0128  582
scale(border_dist)-Tayassu pecari            1.5668 1.0038 1791
scale(border_dist)-Tremarctos ornatus        2.1304 1.0180  712
scale(FLII)-Cuniculus paca                   2.3511 1.0067 1244
scale(FLII)-Cuniculus taczanowskii           2.6829 1.0059 1063
scale(FLII)-Dasyprocta fuliginosa            1.8947 1.0020 2031
scale(FLII)-Dasypus novemcinctus             2.3114 1.0006 1585
scale(FLII)-Eira barbara                     1.8436 1.0030 1886
scale(FLII)-Herpailurus yagouaroundi         1.5243 1.0030 2015
scale(FLII)-Leopardus pardalis               2.1510 1.0037 1703
scale(FLII)-Leopardus tigrinus               1.4972 1.0041 1478
scale(FLII)-Leopardus wiedii                 2.1298 1.0048 1552
scale(FLII)-Mazama murelia                   1.9045 1.0044 2126
scale(FLII)-Mazama rufina                    1.4430 1.0035 1984
scale(FLII)-Mazama zamora                    1.8657 1.0039 1862
scale(FLII)-Nasuella olivacea                1.7966 1.0038 1966
scale(FLII)-Odocoileus ustus                 0.5796 1.0008 1262
scale(FLII)-Panthera onca                    1.9370 1.0121 1969
scale(FLII)-Pecari tajacu                    2.3174 1.0011 1401
scale(FLII)-Pudu mephistophiles              1.7562 1.0070 1478
scale(FLII)-Puma concolor                    0.7157 1.0038 2120
scale(FLII)-Tapirus pinchaque                1.8256 1.0041 1455
scale(FLII)-Tayassu pecari                   1.9851 1.0012 1486
scale(FLII)-Tremarctos ornatus               1.5779 1.0018 1107

Detection (logit scale): 
                                          Mean     SD    2.5%     50%   97.5%
(Intercept)-Cuniculus paca             -0.6424 0.2900 -1.2149 -0.6438 -0.0720
(Intercept)-Cuniculus taczanowskii     -1.7702 0.4490 -2.7464 -1.7377 -0.9548
(Intercept)-Dasyprocta fuliginosa      -1.2893 0.4466 -2.1876 -1.2715 -0.4573
(Intercept)-Dasypus novemcinctus       -0.7070 0.2595 -1.1935 -0.7135 -0.2144
(Intercept)-Eira barbara               -2.1585 0.6826 -3.6464 -2.1322 -0.9573
(Intercept)-Herpailurus yagouaroundi   -1.9464 0.8436 -3.8952 -1.8817 -0.4649
(Intercept)-Leopardus pardalis         -1.6179 0.5637 -2.7746 -1.5921 -0.5733
(Intercept)-Leopardus tigrinus         -2.1589 0.5865 -3.4348 -2.1102 -1.1716
(Intercept)-Leopardus wiedii           -1.9765 0.7659 -3.6908 -1.9062 -0.6952
(Intercept)-Mazama murelia             -1.0338 0.7232 -2.4749 -1.0383  0.4868
(Intercept)-Mazama rufina              -1.1736 0.3100 -1.7987 -1.1738 -0.5846
(Intercept)-Mazama zamora              -0.4904 0.7480 -1.9174 -0.5091  1.0138
(Intercept)-Nasuella olivacea          -2.1143 0.5633 -3.3476 -2.0632 -1.1497
(Intercept)-Odocoileus ustus           -1.4062 0.2018 -1.8301 -1.4017 -1.0214
(Intercept)-Panthera onca              -2.0800 0.6023 -3.3270 -2.0604 -0.9661
(Intercept)-Pecari tajacu              -0.4912 0.2748 -1.0344 -0.4862  0.0380
(Intercept)-Pudu mephistophiles        -1.0344 0.3724 -1.7867 -1.0305 -0.3513
(Intercept)-Puma concolor              -1.6474 0.3571 -2.3843 -1.6292 -1.0082
(Intercept)-Tapirus pinchaque          -1.3769 0.2649 -1.9087 -1.3697 -0.8701
(Intercept)-Tayassu pecari             -2.0516 0.8308 -3.8600 -1.9677 -0.6113
(Intercept)-Tremarctos ornatus         -2.0407 0.2550 -2.5558 -2.0373 -1.5709
scale(effort)-Cuniculus paca            0.5941 0.3222  0.0704  0.5559  1.3369
scale(effort)-Cuniculus taczanowskii    0.2196 0.3255 -0.4109  0.2160  0.8732
scale(effort)-Dasyprocta fuliginosa     0.4998 0.3619 -0.1389  0.4689  1.3262
scale(effort)-Dasypus novemcinctus      0.1483 0.2112 -0.2477  0.1373  0.5915
scale(effort)-Eira barbara              0.4599 0.3983 -0.2232  0.4266  1.3920
scale(effort)-Herpailurus yagouaroundi  0.4374 0.4310 -0.3501  0.4034  1.4110
scale(effort)-Leopardus pardalis        0.4425 0.3436 -0.1584  0.4214  1.2217
scale(effort)-Leopardus tigrinus        0.4386 0.3531 -0.1774  0.4105  1.2368
scale(effort)-Leopardus wiedii          0.4079 0.4269 -0.3714  0.3843  1.3061
scale(effort)-Mazama murelia            0.5083 0.3991 -0.1755  0.4747  1.4221
scale(effort)-Mazama rufina             0.6507 0.3658  0.0723  0.5947  1.4992
scale(effort)-Mazama zamora             0.3601 0.4379 -0.5240  0.3640  1.2397
scale(effort)-Nasuella olivacea         0.1520 0.3335 -0.4905  0.1504  0.8114
scale(effort)-Odocoileus ustus          0.6758 0.3314  0.1534  0.6451  1.4367
scale(effort)-Panthera onca             0.5287 0.4281 -0.2113  0.4899  1.4977
scale(effort)-Pecari tajacu             0.5210 0.2782  0.0491  0.4976  1.1729
scale(effort)-Pudu mephistophiles      -0.1184 0.3198 -0.7795 -0.1077  0.4649
scale(effort)-Puma concolor             0.1284 0.2488 -0.3518  0.1265  0.6261
scale(effort)-Tapirus pinchaque         0.6220 0.3180  0.0972  0.5827  1.3423
scale(effort)-Tayassu pecari            0.4451 0.4056 -0.2844  0.4191  1.3418
scale(effort)-Tremarctos ornatus        0.3831 0.2472 -0.0533  0.3667  0.9047
                                         Rhat  ESS
(Intercept)-Cuniculus paca             1.0008 2714
(Intercept)-Cuniculus taczanowskii     1.0033 2353
(Intercept)-Dasyprocta fuliginosa      1.0060 2420
(Intercept)-Dasypus novemcinctus       1.0005 2825
(Intercept)-Eira barbara               1.0066 1027
(Intercept)-Herpailurus yagouaroundi   1.0081 1070
(Intercept)-Leopardus pardalis         0.9998 1307
(Intercept)-Leopardus tigrinus         1.0018 1205
(Intercept)-Leopardus wiedii           1.0209  768
(Intercept)-Mazama murelia             1.0020 2684
(Intercept)-Mazama rufina              1.0000 2845
(Intercept)-Mazama zamora              1.0168 2676
(Intercept)-Nasuella olivacea          1.0076 1384
(Intercept)-Odocoileus ustus           1.0031 2611
(Intercept)-Panthera onca              1.0077 1229
(Intercept)-Pecari tajacu              1.0058 3000
(Intercept)-Pudu mephistophiles        1.0029 2663
(Intercept)-Puma concolor              1.0005 2224
(Intercept)-Tapirus pinchaque          1.0006 3000
(Intercept)-Tayassu pecari             1.0219  992
(Intercept)-Tremarctos ornatus         1.0070 1312
scale(effort)-Cuniculus paca           1.0008 2461
scale(effort)-Cuniculus taczanowskii   1.0027 2829
scale(effort)-Dasyprocta fuliginosa    1.0003 2675
scale(effort)-Dasypus novemcinctus     1.0040 3186
scale(effort)-Eira barbara             1.0033 2699
scale(effort)-Herpailurus yagouaroundi 1.0003 2833
scale(effort)-Leopardus pardalis       1.0031 2791
scale(effort)-Leopardus tigrinus       1.0018 3000
scale(effort)-Leopardus wiedii         1.0106 2729
scale(effort)-Mazama murelia           1.0019 2623
scale(effort)-Mazama rufina            1.0084 1972
scale(effort)-Mazama zamora            1.0015 3000
scale(effort)-Nasuella olivacea        1.0035 3000
scale(effort)-Odocoileus ustus         1.0015 2538
scale(effort)-Panthera onca            1.0000 3000
scale(effort)-Pecari tajacu            1.0136 2753
scale(effort)-Pudu mephistophiles      1.0041 2594
scale(effort)-Puma concolor            1.0033 2825
scale(effort)-Tapirus pinchaque        1.0017 2478
scale(effort)-Tayassu pecari           1.0139 2725
scale(effort)-Tremarctos ornatus       1.0060 2812

----------------------------------------
    Spatial Covariance
----------------------------------------
        Mean     SD  2.5%    50%  97.5%   Rhat ESS
phi-1 0.0004 0.0031 0e+00 0.0001 0.0004 2.3686  66
phi-2 0.0161 0.0128 1e-04 0.0149 0.0394 1.0610  59
phi-3 0.0173 0.0127 2e-04 0.0163 0.0396 1.0460 144
phi-4 0.0153 0.0132 1e-04 0.0127 0.0396 1.1766 123
phi-5 0.0179 0.0126 3e-04 0.0169 0.0396 1.0119 470

Bayesian p-values can be inspected to check for lack of fit (overall or by species). Lack of fit at significance level = 0.05 is indicated by Bayesian p-values below 0.025 or greater than 0.975. The overall Bayesian p-value (Bpvalue) indicates no problems with lack of fit. Likewise, species-level Bayesian p-values (Bpvalue_species) indicate no lack of fit for any species.

Gelman and Rubin’s convergence diagnostic: Approximate convergence is diagnosed when the upper limit is close to 1.

Convergence is diagnosed when the chains have ‘forgotten’ their initial values, and the output from all chains is indistinguishable. The gelman.diag diagnostic is applied to a single variable from the chain. It is based a comparison of within-chain and between-chain variances, and is similar to a classical analysis of variance.

Values substantially above 1 indicate lack of convergence.

Model Diagnostics

Code
#| eval: true
#| echo: true
#| code-fold: true
#| warning: false
#| message: false
# Extract posterior draws for later use
posterior1 <- as.array(out.sp)

# Trace plots to check chain mixing. Extract posterior samples and bind in a single matrix.
POSTERIOR.MATRIX <- cbind(out.sp$alpha.comm.samples, 
                          out.sp$beta.comm.samples,  
                          out.sp$alpha.samples, 
                          out.sp$beta.samples)

# Matrix output is all chains combined, split into 3 chains.
CHAIN.1 <- as.mcmc(POSTERIOR.MATRIX[1:1000,])
CHAIN.2 <- as.mcmc(POSTERIOR.MATRIX[1001:2000,])
CHAIN.3 <- as.mcmc(POSTERIOR.MATRIX[2001:3000,])
# CHAIN.4 <- as.mcmc(POSTERIOR.MATRIX[8001:10000,])

# Bind four chains as coda mcmc.list object.
POSTERIOR.CHAINS <- mcmc.list(CHAIN.1, CHAIN.2, CHAIN.3)#, CHAIN.4)

# Create an empty folder.
# dir.create ("Beetle_plots")

# Plot chain mixing of each parameter to a multi-panel plot and save to the new folder. ART 5 mins

######################################
#### SAVE Diagnostics at PDF
# MCMCtrace(POSTERIOR.CHAINS, params = "all", Rhat = TRUE, n.eff = TRUE)#, pdf = TRUE, filename = "Beetle_240909_traceplots.pdf", wd = "Beetle_plots")



#mcmc_trace(fit.commu, parms = c("beta.ranef.cont.border_dist.mean"))

#posterior2 <- extract(fit.commu, inc_warmup = TRUE, permuted = FALSE)

#color_scheme_set("mix-blue-pink")
#p <- mcmc_trace(posterior1,  pars = c("mu", "tau"), n_warmup = 300,
#                facet_args = list(nrow = 2, labeller = label_parsed))
#p + facet_text(size = 15)



#outMCMC <- fit.commu #Convert output to MCMC object
#diagnostics chains 

# all as pdf
# MCMCtrace(outMCMC)

# MCMCtrace(outMCMC, params = c("alpha0"), type = 'trace', Rhat = TRUE, n.eff = TRUE)

# MCMCtrace(outMCMC, params = c("beta0"), type = 'trace', Rhat = TRUE, n.eff = TRUE)

# MCMCtrace(outMCMC, params = c("beta.ranef.cont.border_dist"), type = 'trace', Rhat = TRUE, n.eff = TRUE)

# MCMCtrace(out.sp, params = c("beta.ranef.cont.border_dist.mean"), type = 'trace', pdf = F, Rhat = TRUE, n.eff = TRUE)

# MCMCtrace(outMCMC, params = c("beta.ranef.cont.elev"), type = 'trace', Rhat = TRUE, n.eff = TRUE)

# MCMCtrace(outMCMC, params = c("beta.ranef.cont.elev.mean"), type = 'trace', pdf = F, Rhat = TRUE, n.eff = TRUE)


### density
# MCMCtrace(outMCMC, params = c("Nspecies"), ISB = FALSE, pdf = F, exact = TRUE, post_zm = TRUE, type = 'density', Rhat = TRUE, n.eff = TRUE, ind = TRUE)

### density
# MCMCtrace(outMCMC, params = c("beta.ranef.cont.elev.mean"), ISB = FALSE, pdf = F, exact = TRUE, post_zm = TRUE, type = 'density', Rhat = TRUE, n.eff = TRUE, ind = TRUE)

### density
#MCMCtrace(outMCMC, params = c("beta.ranef.cont.border_dist.mean"), ISB = FALSE, pdf = F, exact = TRUE, post_zm = TRUE, type = 'density', Rhat = TRUE, n.eff = TRUE, ind = TRUE)

#coda::gelman.diag(outMCMC,  multivariate = FALSE, transform=FALSE)
                    
# coda::gelman.plot(outMCMC,  multivariate = FALSE)



# 
# mcmc_intervals(outMCMC, pars = c("Nspecies_in_AP[1]",
#                                  "Nspecies_in_AP[2]"),
#                point_est = "mean",
#                prob = 0.75, prob_outer = 0.95) +
#   ggtitle("Number of species") + 
#   scale_y_discrete(labels = c("Nspecies_in_AP[1]"=levels(sitecovs$in_AP)[1],
#              "Nspecies_in_AP[2]"=levels(sitecovs$in_AP)[2]))
# 
# #Continuous
# p <- mcmc_intervals(outMCMC, 
#                pars = c("beta.ranef.cont.border_dist.mean",
#                          #"beta.ranef.cont.elev.mean",
#                         "beta.ranef.categ.in_AP.mean[2]"))
# 
# # relabel parameters
# p + scale_y_discrete(
#   labels = c("beta.ranef.cont.border_dist.mean"="Dist_border",
#                          #"beta.ranef.cont.elev.mean"="Elevation",
#                         "beta.ranef.categ.in_AP.mean[2]"="in_AP")
# ) +
#   ggtitle("Treatment effect on all species")
# 

Posterior Summary (effect)

Community effects

Code
# Create simple plot summaries using MCMCvis package.
# Detection covariate effects --------- 
MCMCplot(out.sp$alpha.comm.samples, ref_ovl = TRUE, ci = c(50, 95))
# Occupancy community-level effects 
MCMCplot(out.sp$beta.comm.samples, ref_ovl = TRUE, ci = c(50, 95))
(a) Detection
(b) Occupancy
Figure 1: Community effects

Species effects

Code
# Occupancy species-level effects 
MCMCplot(out.sp$beta.samples[,22:42], ref_ovl = TRUE, ci = c(50, 95))

# Occupancy species-level effects 
MCMCplot(out.sp$beta.samples[,43:63], ref_ovl = TRUE, ci = c(50, 95))

# Occupancy species-level effects 
MCMCplot(out.sp$beta.samples[,64:84], ref_ovl = TRUE, ci = c(50, 95))
(a) elevation
(b) distance border
(c) FLII
Figure 2: Species effects

Species effects using bayesplot

Code
library(bayesplot)
#mcmc_areas(outMCMC, regex_pars = "Nspecies_in_AP")
# mcmc_areas(outMCMC, regex_pars = "Nspecies_in_AP")

mcmc_intervals(out.sp$beta.samples[,22:42] , point_est = "mean",
               prob = 0.75, prob_outer = 0.95) + 
  geom_vline(xintercept = 0, color = "red", linetype = "dashed", size = 0.5)
Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
ℹ Please use `linewidth` instead.

Code
mcmc_intervals(out.sp$beta.samples[,43:63] , point_est = "mean",
               prob = 0.75, prob_outer = 0.95) + 
  geom_vline(xintercept = 0, color = "red", linetype = "dashed", size = 0.5)

Code
mcmc_intervals(out.sp$beta.samples[,64:84] , point_est = "mean",
               prob = 0.75, prob_outer = 0.95) + 
  geom_vline(xintercept = 0, color = "red", linetype = "dashed", size = 0.5)

Prediction as graph

This prediction uses the non spatial model

Code
# 6. Prediction -----------------------------------------------------------
# Predict occupancy along a gradient of elev   
# Create a set of values across the range of observed elev values
elev.pred.vals <- seq(min(data_list$occ.covs$elev), 
                              max(data_list$occ.covs$elev), 
                              length.out = 100)
# Scale predicted values by mean and standard deviation used to fit the model
elev.pred.vals.scale <- (elev.pred.vals - mean(data_list$occ.covs$elev)) / 
                             sd(data_list$occ.covs$elev)
# Create a set of values across the range of observed elev values
border_dist.pred.vals <- seq(min(data_list$occ.covs$border_dist), 
                              max(data_list$occ.covs$border_dist), 
                              length.out = 100)
# Scale predicted values by mean and standard deviation used to fit the model
border_dist.pred.vals.scale <- (border_dist.pred.vals -
                                  mean(data_list$occ.covs$border_dist)) /
                                  sd(data_list$occ.covs$border_dist)

# Create a set of values across the range of observed FLII values
FLII.pred.vals <- seq(min(data_list$occ.covs$FLII), 
                              max(data_list$occ.covs$FLII), 
                              length.out = 100)
# Scale predicted values by mean and standard deviation used to fit the model
FLII.pred.vals.scale <- (FLII.pred.vals -
                                  mean(data_list$occ.covs$FLII)) /
                                  sd(data_list$occ.covs$FLII)

# Predict occupancy across elev  values at mean values of all other variables
pred.df1 <- as.matrix(data.frame(intercept = 1, 
                                 elev = elev.pred.vals.scale, 
                                 border_dist = 0,
                                 FLII=0))#, catchment = 0, density = 0, 
                         # slope = 0))
# Predict occupancy across elev  values at mean values of all other variables
pred.df2 <- as.matrix(data.frame(intercept = 1, elev = 0, 
                         border_dist = border_dist.pred.vals.scale,
                         FLII= 0 ))#, catchment = 0, density = 0, 
                         # slope = 0))
# Predict occupancy across elev  values at mean values of all other variables
pred.df3 <- as.matrix(data.frame(intercept = 1, elev = 0, 
                         border_dist = 0,
                         FLII= FLII.pred.vals.scale ))#, catchment = 0, density = 0, 
                         # slope = 0))

out.pred1 <- predict(out.null, pred.df1) # using non spatial
str(out.pred1)
List of 3
 $ psi.0.samples: num [1:1500, 1:21, 1:100] 0.0519 0.1373 0.218 0.3519 0.1479 ...
 $ z.0.samples  : int [1:1500, 1:21, 1:100] 0 0 0 1 1 0 0 1 0 0 ...
 $ call         : language predict.msPGOcc(object = out.null, X.0 = pred.df1)
 - attr(*, "class")= chr "predict.msPGOcc"
Code
psi.0.quants <- apply(out.pred1$psi.0.samples, c(2, 3), quantile, 
                          prob = c(0.025, 0.5, 0.975))
sp.codes <- attr(data_list$y, "dimnames")[[1]]
psi.plot.dat <- data.frame(psi.med = c(t(psi.0.quants[2, , ])), 
                                 psi.low = c(t(psi.0.quants[1, , ])), 
                                 psi.high = c(t(psi.0.quants[3, , ])), 
                           elev = elev.pred.vals, 
                                 sp.codes = rep(sp.codes, 
                                                each = length(elev.pred.vals)))

ggplot(psi.plot.dat, aes(x = elev, y = psi.med)) + 
  geom_ribbon(aes(ymin = psi.low, ymax = psi.high), fill = 'grey70') +
  geom_line() + 
  facet_wrap(vars(sp.codes)) + 
  theme_bw() + 
  labs(x = 'elevation (m)', y = 'Occupancy Probability') 

Code
out.pred2 <- predict(out.null, pred.df2) # using non spatial
str(out.pred2)
List of 3
 $ psi.0.samples: num [1:1500, 1:21, 1:100] 0.00161 0.00885 0.03237 0.04141 0.00408 ...
 $ z.0.samples  : int [1:1500, 1:21, 1:100] 0 0 0 0 0 0 0 0 0 0 ...
 $ call         : language predict.msPGOcc(object = out.null, X.0 = pred.df2)
 - attr(*, "class")= chr "predict.msPGOcc"
Code
psi.0.quants <- apply(out.pred2$psi.0.samples, c(2, 3), quantile, 
                          prob = c(0.025, 0.5, 0.975))
sp.codes <- attr(data_list$y, "dimnames")[[1]]
psi.plot.dat <- data.frame(psi.med = c(t(psi.0.quants[2, , ])), 
                                 psi.low = c(t(psi.0.quants[1, , ])), 
                                 psi.high = c(t(psi.0.quants[3, , ])), 
                           border_dist = border_dist.pred.vals, 
                                 sp.codes = rep(sp.codes, 
                                                each = length(border_dist.pred.vals)))

ggplot(psi.plot.dat, aes(x = border_dist/1000, y = psi.med)) + 
  geom_ribbon(aes(ymin = psi.low, ymax = psi.high), fill = 'grey70') +
  geom_line() + 
  facet_wrap(vars(sp.codes)) + 
  theme_bw() + 
  labs(x = 'border_dist (Km)', y = 'Occupancy Probability') 

Code
out.pred3 <- predict(out.null, pred.df3) # using non spatial
str(out.pred3)
List of 3
 $ psi.0.samples: num [1:1500, 1:21, 1:100] 0.0035 0.00575 0.0111 0.00528 0.00322 ...
 $ z.0.samples  : int [1:1500, 1:21, 1:100] 0 0 0 0 0 0 0 0 0 0 ...
 $ call         : language predict.msPGOcc(object = out.null, X.0 = pred.df3)
 - attr(*, "class")= chr "predict.msPGOcc"
Code
psi.0.quants <- apply(out.pred3$psi.0.samples, c(2, 3), quantile, 
                          prob = c(0.025, 0.5, 0.975))
sp.codes <- attr(data_list$y, "dimnames")[[1]]
psi.plot.dat <- data.frame(psi.med = c(t(psi.0.quants[2, , ])), 
                                 psi.low = c(t(psi.0.quants[1, , ])), 
                                 psi.high = c(t(psi.0.quants[3, , ])), 
                           FLII = FLII.pred.vals, 
                                 sp.codes = rep(sp.codes, 
                                                each = length(FLII.pred.vals)))

ggplot(psi.plot.dat, aes(x = FLII/1000, y = psi.med)) + 
  geom_ribbon(aes(ymin = psi.low, ymax = psi.high), fill = 'grey70') +
  geom_line() + 
  facet_wrap(vars(sp.codes)) + 
  theme_bw() + 
  labs(x = 'FLII', y = 'Occupancy Probability') 

Spatial Prediction in FLII

Code
#aggregate  resolution to (factor = 3)
#transform coord data to UTM
elevation_UTM <- project(elevation_14, "EPSG:10603")
elevation_17.aggregate <- aggregate(elevation_UTM, fact=10)
res(elevation_17.aggregate)

FLII_UTM <- project(FLII2016, "EPSG:10603") |> crop(elevation_UTM)
# Calculate the min of non-NA values
# na.rm = TRUE is essential to ignore NAs when calculating the mean
min_val <- global(FLII_UTM, "min", na.rm = TRUE, na.policy = "only")[1, 1]
# Replace NA values with the calculated min
FLII_UTM[is.na(FLII_UTM)] <- min_val

FLII_UTM.aggregate <- aggregate(FLII_UTM, fact=10)
res(FLII_UTM.aggregate)

# Convert the SpatRaster to a data frame with coordinates
df_coords <- as.data.frame(FLII_UTM.aggregate, xy = TRUE)
names(df_coords) <-c("X","Y","FLII")

FLII.pred <- (df_coords$FLII - mean(data_list$occ.covs$FLII)) / sd(data_list$occ.covs$FLII)


############### Predict new data ############### 
# we predict at one covariate varing and others at mean value = 0
# intercept = 1, elev = 0, border_dist = 0, FLII= 0
# in that order
################ ################ ################ 
predict_data <- cbind(1, 0, 0, FLII.pred)
colnames(predict_data) <- c("intercept",
                            "elev",
                            "border_dist",
                            "FLII" )

# X.0 <- cbind(1, 1, elev.pred)#, elev.pred^2)

# coords.0 <- as.matrix(hbefElev[, c('Easting', 'Northing')])
out.sp.ms.pred <- predict(out.sp, 
                          X.0=predict_data, 
                          df_coords[,1:2],
                          threads=4) #Warning :'threads' is not an argument

# extract the array of interest= occupancy
predicted_array <- out.sp.ms.pred$psi.0.samples



dim(predicted_array)
# df_plot <- NA # empty column
predicted_raster_list <- list() # rast(nrows = 52, ncols = 103,
                         #ext(elevation_17.aggregate), 
                         # crs = "EPSG:32717")

###################################################
# simpler way to make mean in the array by species
# array order: itera=3000, sp=22, pixels=5202
# we wan to keep index 2 and 3
library(plyr)
aresult = (plyr::aaply(predicted_array, # mean fo all iterations
                       c(2,3), 
                       mean))

##############################################
#### Loop to make rasters and put in a list
# array order: itera=3000, sp=22, pixels=5202
for (i in 1:dim(predicted_array)[2]){
 # Convert array slice to data frame
 # df_plot[i] <- as.data.frame(predicted_array[1, i, ]) # sp_i
 # df_plot[i] <- as.vector(aresult[i,]) # Extract sp
 # Producing an SDM for all (posterior mean)
 plot.dat <- data.frame(x = df_coords$X, 
                        y = df_coords$Y, 
                        psi.sp = as.vector(aresult[i,]))
 pred_rast <- rast(plot.dat, 
                   type = "xyz", 
                   crs = "EPSG:10603") # Replace EPSG:4326 with your CRS
 predicted_raster_list[[i]] <- pred_rast
}

# Convert the list to a SpatRaster stack
predictad_raster_stack <- rast(predicted_raster_list)
# put species names
names(predictad_raster_stack) <- selected.sp

plot(predictad_raster_stack)

# get the mean
predicted_mean <- mean(predictad_raster_stack)

plot(predicted_mean, main="mean occupancy")

mapview(predicted_mean) + mapview(AP_Llanganates_UTM_line)
# 

Package Citation

Code
pkgs <- cite_packages(output = "paragraph", pkgs="Session", out.dir = ".")
# knitr::kable(pkgs)
pkgs

We used R v. 4.4.2 (R Core Team 2024) and the following R packages: abind v. 1.4.8 (Plate and Heiberger 2024), bayesplot v. 1.14.0 (Gabry et al. 2019; Gabry and Mahr 2025), beepr v. 2.0 (Bååth 2024), camtrapR v. 3.0.0 (Niedballa et al. 2016), coda v. 0.19.4.1 (Plummer et al. 2006), DT v. 0.34.0 (Xie et al. 2025), elevatr v. 0.99.0 (Hollister et al. 2023), maps v. 3.4.3 (Becker et al. 2025), mapview v. 2.11.4 (Appelhans et al. 2025), MCMCvis v. 0.16.3 (Youngflesh 2018), sf v. 1.0.21 (Pebesma 2018; Pebesma and Bivand 2023), snow v. 0.4.4 (Tierney et al. 2021), snowfall v. 1.84.6.3 (Knaus 2023), spOccupancy v. 0.8.0 (Doser et al. 2022, 2024; Doser, Finley, and Banerjee 2023), terra v. 1.8.70 (Hijmans 2025), tictoc v. 1.2.1 (Izrailev 2024), tidyverse v. 2.0.0 (Wickham et al. 2019), tmap v. 4.2 (Tennekes 2018).

Sesion info

Code
print(sessionInfo(), locale = FALSE)
R version 4.4.2 (2024-10-31 ucrt)
Platform: x86_64-w64-mingw32/x64
Running under: Windows 10 x64 (build 19045)

Matrix products: internal


attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] abind_1.4-8       lubridate_1.9.4   forcats_1.0.0     stringr_1.5.2    
 [5] dplyr_1.1.4       purrr_1.1.0       readr_2.1.5       tidyr_1.3.1      
 [9] tibble_3.2.1      ggplot2_4.0.0     tidyverse_2.0.0   spOccupancy_0.8.0
[13] camtrapR_3.0.0    snowfall_1.84-6.3 snow_0.4-4        beepr_2.0        
[17] coda_0.19-4.1     MCMCvis_0.16.3    tictoc_1.2.1      bayesplot_1.14.0 
[21] elevatr_0.99.0    terra_1.8-70      tmap_4.2          maps_3.4.3       
[25] mapview_2.11.4    sf_1.0-21         DT_0.34.0         readxl_1.4.3     
[29] grateful_0.3.0   

loaded via a namespace (and not attached):
  [1] RColorBrewer_1.1-3      tensorA_0.36.2.1        rstudioapi_0.17.1      
  [4] audio_0.1-11            jsonlite_2.0.0          wk_0.9.4               
  [7] magrittr_2.0.3          farver_2.1.2            nloptr_2.1.1           
 [10] rmarkdown_2.30          vctrs_0.6.5             minqa_1.2.8            
 [13] base64enc_0.1-3         RcppNumerical_0.6-0     progress_1.2.3         
 [16] htmltools_0.5.8.1       leafsync_0.1.0          distributional_0.5.0   
 [19] curl_7.0.0              raster_3.6-32           cellranger_1.1.0       
 [22] s2_1.1.9                sass_0.4.10             bslib_0.9.0            
 [25] slippymath_0.3.1        KernSmooth_2.23-24      htmlwidgets_1.6.4      
 [28] plyr_1.8.9              cachem_1.1.0            stars_0.6-8            
 [31] uuid_1.2-1              mime_0.13               lifecycle_1.0.4        
 [34] iterators_1.0.14        pkgconfig_2.0.3         cols4all_0.8-1         
 [37] Matrix_1.7-1            R6_2.6.1                fastmap_1.2.0          
 [40] shiny_1.9.1             digest_0.6.37           colorspace_2.1-1       
 [43] leafem_0.2.4            crosstalk_1.2.1         labeling_0.4.3         
 [46] lwgeom_0.2-14           progressr_0.15.0        spacesXYZ_1.6-0        
 [49] timechange_0.3.0        httr_1.4.7              mgcv_1.9-1             
 [52] compiler_4.4.2          microbenchmark_1.5.0    proxy_0.4-27           
 [55] withr_3.0.2             doParallel_1.0.17       backports_1.5.0        
 [58] brew_1.0-10             S7_0.2.1                DBI_1.2.3              
 [61] logger_0.4.0            MASS_7.3-61             maptiles_0.10.0        
 [64] tmaptools_3.3           leaflet_2.2.3           classInt_0.4-11        
 [67] tools_4.4.2             units_0.8-7             leaflegend_1.2.1       
 [70] httpuv_1.6.16           glue_1.8.0              satellite_1.0.5        
 [73] nlme_3.1-166            promises_1.3.3          grid_4.4.2             
 [76] checkmate_2.3.2         reshape2_1.4.4          generics_0.1.3         
 [79] leaflet.providers_2.0.0 gtable_0.3.6            tzdb_0.4.0             
 [82] shinyBS_0.61.1          class_7.3-22            data.table_1.17.8      
 [85] hms_1.1.3               sp_2.2-0                RANN_2.6.2             
 [88] foreach_1.5.2           pillar_1.11.1           posterior_1.6.1        
 [91] later_1.4.2             splines_4.4.2           lattice_0.22-6         
 [94] tidyselect_1.2.1        knitr_1.50              svglite_2.1.3          
 [97] stats4_4.4.2            xfun_0.52               shinydashboard_0.7.3   
[100] leafpop_0.1.0           stringi_1.8.4           rematch_2.0.0          
[103] yaml_2.3.10             boot_1.3-31             evaluate_1.0.4         
[106] codetools_0.2-20        cli_3.6.5               RcppParallel_5.1.9     
[109] systemfonts_1.1.0       xtable_1.8-4            jquerylib_0.1.4        
[112] secr_5.1.0              dichromat_2.0-0.1       Rcpp_1.1.0             
[115] spAbundance_0.2.1       png_0.1-8               XML_3.99-0.18          
[118] parallel_4.4.2          prettyunits_1.2.0       lme4_1.1-35.5          
[121] mvtnorm_1.3-2           scales_1.4.0            e1071_1.7-16           
[124] crayon_1.5.3            rlang_1.1.6            

References

Appelhans, Tim, Florian Detsch, Christoph Reudenbach, and Stefan Woellauer. 2025. mapview: Interactive Viewing of Spatial Data in r. https://CRAN.R-project.org/package=mapview.
Bååth, Rasmus. 2024. beepr: Easily Play Notification Sounds on Any Platform. https://CRAN.R-project.org/package=beepr.
Becker, Richard A., Allan R. Wilks, Ray Brownrigg, Thomas P. Minka, and Alex Deckmyn. 2025. maps: Draw Geographical Maps. https://CRAN.R-project.org/package=maps.
Doser, Jeffrey W., Andrew O. Finley, and Sudipto Banerjee. 2023. “Joint Species Distribution Models with Imperfect Detection for High-Dimensional Spatial Data.” Ecology, e4137. https://doi.org/10.1002/ecy.4137.
Doser, Jeffrey W., Andrew O. Finley, Marc Kéry, and Elise F. Zipkin. 2022. spOccupancy: An r Package for Single-Species, Multi-Species, and Integrated Spatial Occupancy Models.” Methods in Ecology and Evolution 13: 1670–78. https://doi.org/10.1111/2041-210X.13897.
Doser, Jeffrey W., Andrew O. Finley, Sarah P. Saunders, Marc Kéry, Aaron S. Weed, and Elise F. Zipkin. 2024. “Modeling Complex Species-Environment Relationships Through Spatially-Varying Coefficient Occupancy Models.” Journal of Agricultural, Biological, and Environmental Statistics. https://doi.org/10.1007/s13253-023-00595-6.
Gabry, Jonah, and Tristan Mahr. 2025. bayesplot: Plotting for Bayesian Models.” https://mc-stan.org/bayesplot/.
Gabry, Jonah, Daniel Simpson, Aki Vehtari, Michael Betancourt, and Andrew Gelman. 2019. “Visualization in Bayesian Workflow.” J. R. Stat. Soc. A 182: 389–402. https://doi.org/10.1111/rssa.12378.
Hijmans, Robert J. 2025. terra: Spatial Data Analysis. https://CRAN.R-project.org/package=terra.
Hollister, Jeffrey, Tarak Shah, Jakub Nowosad, Alec L. Robitaille, Marcus W. Beck, and Mike Johnson. 2023. elevatr: Access Elevation Data from Various APIs. https://doi.org/10.5281/zenodo.8335450.
Izrailev, Sergei. 2024. tictoc: Functions for Timing r Scripts, as Well as Implementations of Stack and StackList Structures. https://CRAN.R-project.org/package=tictoc.
Knaus, Jochen. 2023. snowfall: Easier Cluster Computing (Based on snow). https://CRAN.R-project.org/package=snowfall.
Niedballa, Jürgen, Rahel Sollmann, Alexandre Courtiol, and Andreas Wilting. 2016. camtrapR: An r Package for Efficient Camera Trap Data Management.” Methods in Ecology and Evolution 7 (12): 1457–62. https://doi.org/10.1111/2041-210X.12600.
Pebesma, Edzer. 2018. Simple Features for R: Standardized Support for Spatial Vector Data.” The R Journal 10 (1): 439–46. https://doi.org/10.32614/RJ-2018-009.
Pebesma, Edzer, and Roger Bivand. 2023. Spatial Data Science: With applications in R. Chapman and Hall/CRC. https://doi.org/10.1201/9780429459016.
Plate, Tony, and Richard Heiberger. 2024. abind: Combine Multidimensional Arrays. https://CRAN.R-project.org/package=abind.
Plummer, Martyn, Nicky Best, Kate Cowles, and Karen Vines. 2006. CODA: Convergence Diagnosis and Output Analysis for MCMC.” R News 6 (1): 7–11. https://journal.r-project.org/archive/.
R Core Team. 2024. R: A Language and Environment for Statistical Computing. Vienna, Austria: R Foundation for Statistical Computing. https://www.R-project.org/.
Tennekes, Martijn. 2018. tmap: Thematic Maps in R.” Journal of Statistical Software 84 (6): 1–39. https://doi.org/10.18637/jss.v084.i06.
Tierney, Luke, A. J. Rossini, Na Li, and H. Sevcikova. 2021. snow: Simple Network of Workstations. https://CRAN.R-project.org/package=snow.
Wickham, Hadley, Mara Averick, Jennifer Bryan, Winston Chang, Lucy D’Agostino McGowan, Romain François, Garrett Grolemund, et al. 2019. “Welcome to the tidyverse.” Journal of Open Source Software 4 (43): 1686. https://doi.org/10.21105/joss.01686.
Xie, Yihui, Joe Cheng, Xianying Tan, and Garrick Aden-Buie. 2025. DT: A Wrapper of the JavaScript Library DataTables. https://CRAN.R-project.org/package=DT.
Youngflesh, Casey. 2018. MCMCvis: Tools to Visualize, Manipulate, and Summarize MCMC Output.” Journal of Open Source Software 3 (24): 640. https://doi.org/10.21105/joss.00640.

Reuse

Citation

BibTeX citation:
@online{forero2025,
  author = {Forero, German and Wallace, Robert and Zapara-Rios, Galo and
    Isasi-Catalá, Emiliana and J. Lizcano, Diego},
  title = {Llanganates {Spatial} {Factor} {Multi-Species} {Occupancy}
    {Model}},
  date = {2025-08-16},
  url = {https://dlizcano.github.io/Occu_APs_all/blog/2025-11-04-Langanates/},
  langid = {en}
}
For attribution, please cite this work as:
Forero, German, Robert Wallace, Galo Zapara-Rios, Emiliana Isasi-Catalá, and Diego J. Lizcano. 2025. “Llanganates Spatial Factor Multi-Species Occupancy Model.” August 16, 2025. https://dlizcano.github.io/Occu_APs_all/blog/2025-11-04-Langanates/.