Uses MaxEnt from predicts package to test multiple models with different feature class combinations, regularization multipliers, and a user supplied partitioning scheme for training and testing. The function outputs model objects, model results, as well as prediction SpatRasters of each model projected back onto geographic space using the supplied environmental SpatRaster stacks. Note: you will need to install rJava to successfully run this function.

maxent_3D(
  maxent_df,
  wanted_fc,
  wanted_rm,
  wanted_partition = NULL,
  projection_layers,
  occs,
  depth_list
)

Arguments

maxent_df

'data.frame' where the first column is a vector of presences named "p" containing 1's and 0's. Each row represents a cell in the spatRaster volume with an x, y, z coordinate, and 1's are presences while 0's are absences, or background points. Other columns are environmental variable values extracted at the occurrence and background points, and should have the same names as the names of the environmental layers in the projection_layers list of SpatRaster stacks.

wanted_fc

a character vector giving what feature class combinations should be tried. "L" refers to linear, "Q" refers to quadratic, "H" refers to hinge, and "P" refers to product. Should be in the format c("L", "Q", "LQ") etc.

wanted_rm

regularization multipliers to be tried in format c(1:4)

wanted_partition

optional, should be the output of 'partition_3D'. if no partition is supplied, all points will be used for training

projection_layers

list of SpatRaster stacks by depth for predictions, must all be cropped to the depth slice with the largest extent and masked to the accessible area of the matching depth slice. Each element is a depth slice, and each stack should contain all of the environmental variables used in the model with the same names as that used in the model.

occs

data.frame of longitude, latitude, and depth occurrences with columns named "longitude", "latitude", and "depth".

depth_list

vector of depths corresponding to depth slices of list elements of projection_layers. Should be positive and go from shallowest depth to deepest depth

Value

An object of class list with four components:

$models, a list containing each model object produced.

$results, a data.frame where each row is a model corresponding to the list element in $models and $predictions. If there was no partition supplied for training and testing, each column will report the feature class, regularization multiplier, AUC, total coefficients, nonzero coefficients, AICc, and delta AICc. if a partition is used, it will report the average of these statistics across all partitions.

$predictions, a list of spatRaster stacks where each list element is a model corresponding to the rows of $results and elements of $models projected onto the supplied projection_layers. Each layer in the stack is a depth slice.

$partition_results, a list object of the same length as the number of partition groups containing a data.frame of results for each model for each partition. Only produced if a partition is supplied.

Details

The names of the projection_layers should be the same as the column names of the environmental variables in maxent_df. The number of models output will be the number of feature classes multiplied by the number of regularization multipliers. For example, a wanted_fc of c("L", "Q", "P") and a wanted_rm of c(1:3) will output 9 total models.

Examples


library(dplyr)
library(predicts)
library(terra)

# creating list of spatraster stacks where each element is a depth slice
r1_d1 <- rast(ncol = 100, nrow = 100)
set.seed(0)
values(r1_d1) <- as.numeric(sample(c(1:100), size = 1000, replace = TRUE))
#> Warning: [setValues] values were recycled
r2_d1 <- rast(ncol = 100, nrow = 100)
set.seed(0)
values(r2_d1) <- as.numeric(sample(c(1:1000), size = 1000, replace = FALSE))
#> Warning: [setValues] values were recycled
r1_d2 <- r1_d1
values(r1_d2) <- as.numeric(values(r1_d1)+10)
r2_d2 <- r2_d1
values(r2_d2) <- as.numeric(values(r2_d1)+10)
d1 <- c(r1_d1, r2_d1)
names(d1) <- c("valsr1", "valsr2")
d2 <- c(r1_d2, r2_d2)
names(d2) <- c("valsr1", "valsr2")
envlist <- list(d1, d2)

# creating occs and bgs
set.seed(0)
occs <- sample(c(1:nrow(crds(envlist[[1]][[1]]))), size = 50, replace = FALSE)
bgs <- sample(c(1:nrow(crds(envlist[[1]][[1]]))), size = 500, replace = FALSE)

occ_indices <- sample(c(1:nrow(crds(envlist[[1]][[1]]))), size = 50, replace = FALSE)
bg_indices  <- sample(c(1:nrow(crds(envlist[[1]][[1]]))), size = 500, replace = FALSE)

occs_d1 <- crds(envlist[[1]][[1]])[occ_indices[1:25],]
occs_d2 <- crds(envlist[[2]][[1]])[occ_indices[26:50],]
bg_d1   <- crds(envlist[[1]][[1]])[bg_indices[1:250],]
bg_d2   <- crds(envlist[[2]][[1]])[bg_indices[251:500],]

# extracting at occs and bgs
occ_valsr1_d1 <- extract(envlist[[1]][[1]], occs_d1)
occ_valsr1_d2 <- extract(envlist[[2]][[1]], occs_d2)
occ_valsr2_d1 <- extract(envlist[[1]][[2]], occs_d1)
occ_valsr2_d2 <- extract(envlist[[2]][[2]], occs_d2)

occ_valsr1 <- rbind(occ_valsr1_d1, occ_valsr1_d2)
occ_valsr2 <- rbind(occ_valsr2_d1, occ_valsr2_d2)

bg_valsr1_d1 <- extract(envlist[[1]][[1]], bg_d1)
bg_valsr1_d2 <- extract(envlist[[2]][[1]], bg_d2)
bg_valsr2_d1 <- extract(envlist[[1]][[2]], bg_d1)
bg_valsr2_d2 <- extract(envlist[[2]][[2]], bg_d2)

bg_valsr1 <- rbind(bg_valsr1_d1, bg_valsr1_d2)
bg_valsr2 <- rbind(bg_valsr2_d1, bg_valsr2_d2)

valsr1 <- rbind(occ_valsr1, bg_valsr1)
valsr2 <- rbind(occ_valsr2, bg_valsr2)

p1 <- rep(1, times = 50)
p0 <- rep(0, times = 500)
p <- c(p1, p0)

maxdf <- data.frame(p, valsr1, valsr2)

coords <- rbind(occs_d1, occs_d2)
colnames(coords) <- c("longitude", "latitude")
depth_vector     <- c(rep(1, times = 25), rep(2, times = 25))

# Use data.frame instead of cbind so $depth is completely valid inside maxent_3D
occs_dataframe <- data.frame(coords, depth = depth_vector)

# \donttest{
# Pass the clean data.frame to the function
if(requireNamespace("rJava", quietly = TRUE)){
  result <- maxent_3D(maxent_df = maxdf, wanted_fc = c("L", "Q"),
                      wanted_rm = c(1:2), projection_layers = envlist,
                      occs = occs_dataframe, depth_list = c(1,2))
}
#> [1] "running models"
# }