SDMaps2

Christian Kampichler

2023-09-19

SDMaps2 is a program to implement spatial modelling of species distribution and abundance data developed at the Dutch Centre for Field Ornithology. This document aims to introduce the user into its use by working through a series of increasingly complex modelling tasks.

library(SDMaps2)

Introduction

Making species distribution models (SDMs) has become one of the most important tasks of modern ecology (Ahmed et al. 2015). They are used in the course of fundamental investigation as well as for applied aspects. The entire process of making an SDM consists of various steps: First, the data on the biota (e.g. presence-absence or abundance of a given species) and the explanatory environmental data (e.g. climatic data, land-use data)–typically recorded at a finite number of plots, perhaps in a standardised monitoring scheme–must be prepared in a spatially explicit way; second, a model has to be generated that relates presence-absence (P-A) or abundance of the biota to the explanatory variables; third, the model is used to make inter- or extrapolated predictions for the entire area of interest; fourth, the model predictions should be visualised in a map. SDMaps2 aims to do all these steps under a single roof and–optimally–with a single key stroke. Essentially, it consists of sets of wrapper functions to implement otherwise common (or less common) statistical and non-statistical procedures provided by R.

In contrast to its predecessor SDMaps which provides a number of different modelling techniques ranging from GLM and MARS to random forests and artificial neural networks, SDMaps2 concentrates on two of the most powerful methods for spatial modelling: on random forests, implemented with the fast algorithm ranger (Wright and Ziegler 2017), and boosted regression trees, implemented with the fast algorithm XGBoost (Chen and Guestrin 2016; Chen et al. 2021). At the moment, only ranger is fully implemented; the current implementation of XGBoost works only with the defaults of the hyperparameters and yields unsatisfactory models. We hope to be able to add some routines for fine-tuning and optimizing XGBoost models in the near future.

Your first modelling run with SDMaps2

Provide input data

For modelling with SDMaps2 you need to prepare the following items:

Observations

Open the file lancol.csv in your favourite spreadsheet programme. (“lancol” stands for Lanius collurio, the red-backed shrike, which is the species that will accompany you through the majority of examples. In modelling runs, species are often represented by numerical codes, e.g. EURING codes for birds, or abbreviations to avoid the handling of bulky species names.) This file contains the input data to SDMaps2 and consists of geo-referenced information on where the observations were made along with the observations themselves and the corresponding environmental information. In the remainder of this vignette the locations are called the ‘plots’, the data thus are the ‘plotdata’. Let us check them in detail:

  • The first column (“Species”) specifies the species that you want to model. Here, it is only one (lancol), but you may analyse many species in one modelling run.

  • The second column (“plotID”) assigns a unique code to each location where observations were made.

  • Column “observed” contains the observations (for example, absence or presence of the species or the number of individuals counted in the plot). Absence must be coded as 0, presence may be coded as any number larger than zero.

  • Columns “x” and “y” are the geographic coordinates of the plots. Any coordinate reference system may be used, for example the WGS84 coordinate reference system, the Universal Transverse Mercator coordinate system or any national reference system.

  • All the columns to the right of the coordinates are environmental explanatory variables (climatic variables, land-use variables etc.) characterising the plots. We call these variables covariates in the rest of this document.

There are some important rules for naming the columns: “Species”, “plotID”, “observed”, “x” and “y” must be written exactly in this way. The variable names should be without spaces or hyphens (“-“), but the use of the underscore (“_”) is allowed. This also applies to the plot ID’s and the species codes used in column “Species”.

Another advice is how to deal with missing data, when, for example, for some given plots no data are available for one or more covariates. Although this do not pose problems for some modelling techniques, others depend on complete covariate information. SDMaps contains an imputation routine for these cases, but the procedure may cause considerably longer computing times. The general advice is, thus, to avoid missing data in the covariates.

Covariate grids

You must provide a grid with the covariates that will be used as predictors, covering the entire area for which maps have to be made. We call this grid the prediction grid, or shortly, the predgrid. The maps we use in this turorial are stored in directory [your working directory]/grids10km/. Check their names: Apart from their extension, they are identical to the column headers of the covariates in file lancol.csv. Consequently, they must not include spaces or hyphens neither! As you may suspect when you look at the directory name, the maps used here are on a rather coarse grid of 10 x 10 km, which guarantees that runtime of our examples will be short. The maps can be of ASCII or GeoTIFF format. The coordinate reference system must be identical to that used for the observations.

Shapefile with features

Output maps consisting of a grid only, however, may not be very appealing or even hard to read. At least the contours of the predgrid should be made available, but you may be interested to include other informative features such as province borders, rivers etc. Its coordinate reference system has to be the same as the observations and the covariate grids.

Species codes and names

While during modelling work you may not want to deal with bulky species names, you want to see use names in map titles or output filenames to make them more readable. In this case provide a textfile called speciesnames.txt that contains two comma-separated columns “code” (the code or abbreviation you are using during modelling) and “species” (the full species name you want to use in maps and output files).

Prepare data with function data2SDMaps()

Now we can begin with our first SDMaps function, called data2SDMaps(). It reads in all necessary data and converts them into an object of class “list”. This object–we call it the sdmdata–contains all data, paths and modelling information specified by the following arguments. The object can directly be used for a modelling run or can be saved for later use and loaded into the R working space. The saved sdmdata object should not, however, be moved into another directory because of the path definitions it contains! Using it from within another directory or on another computer would cause the analysis to crash (unless you know how to edit it manually). If you want to repeat the analysis on another computer or somewhere else in the directory structure of a computer, invoke data2SDMaps() again at the new position prior to do a modelling run.

All the input data must be provided in certain directories: the plotdata, the contour shapefile and the speciesnames file should reside in the working directory, the covariate grids should be saved in a a separate directory. Here, we set the directories according to our own directory structure; you will have to define your own directories.

Let us check the input data:

Now everything is ready for the first run. Let us make the sdmdata with function data2SDMaps2:

# Provide information on the which coordinate reference system is
# used. Here, we apply the CRS Dealul Piscului 1970/Stereo 70
# (EPSG:31700)–our example comes from Romania–which corresponds to the
# string that is assigned to object crs:
crs <- '+proj=sterea +lat_0=46 +lon_0=25 +k=0.99975 +x_0=500000 +y_0=500000 +ellps=krass +units=m +no_defs'
sdmdata <- data2SDMaps2(# we call the sdmdata simply sdmdata:
                        named = 'sdmdata',
            # the output will be save here (if the
            # directory does not yet exist it will be
            # created):
                        outdir = file.path(getwd(), 'results'),
                        plot.data = 'lancol.csv', 
                        crs = crs, 
                        grids.dir = file.path(getwd(), 'grids10km'),
            # categorical covariates have to be mentioned
            # explicitly:
                        categ.covariate = 'alt_categ')
#> 
#> 
#>  ---------------------------
#>  Preparing data for SDMaps2
#>  ---------------------------
#> 
#>  Checking input...
#>      Checking arguments...Ok
#>      Reading plot data...Ok
#>      Checking column headers...Ok
#>      Checking plotIDs for blanks, hyphens and leading zeroes...Ok
#>      Checking species codes...Ok
#>  Checking input...Ok
#> 
#>  Adding USER-mapdata to plotdata...
#>      Adding alt_categ to data... Ok
#>      Adding alt to data...already in plot data. Adding only to prediction data Ok
#>      Adding bio01 to data...already in plot data. Adding only to prediction data Ok
#>      Adding bio05 to data...already in plot data. Adding only to prediction data Ok
#>      Adding bio06 to data...already in plot data. Adding only to prediction data Ok
#>      Adding bio12 to data...already in plot data. Adding only to prediction data Ok
#>      Adding etp to data...already in plot data. Adding only to prediction data Ok
#>      Adding gr01 to data...already in plot data. Adding only to prediction data Ok
#>      Adding gr02 to data...already in plot data. Adding only to prediction data Ok
#>      Adding gr03 to data...already in plot data. Adding only to prediction data Ok
#>      Adding gr04 to data...already in plot data. Adding only to prediction data Ok
#>      Adding gr05 to data...already in plot data. Adding only to prediction data Ok
#>      Adding gr06 to data...already in plot data. Adding only to prediction data Ok
#>      Adding gr07 to data...already in plot data. Adding only to prediction data Ok
#>      Adding gr08 to data...already in plot data. Adding only to prediction data Ok
#>      Adding gr09 to data...already in plot data. Adding only to prediction data Ok
#>      Adding gr10 to data...already in plot data. Adding only to prediction data Ok
#>      Adding gr11 to data...already in plot data. Adding only to prediction data Ok
#>      Adding gr12 to data...already in plot data. Adding only to prediction data Ok
#>      Adding gr13 to data...already in plot data. Adding only to prediction data Ok
#>      Adding gr14 to data...already in plot data. Adding only to prediction data Ok
#>      Adding gr15 to data...already in plot data. Adding only to prediction data Ok
#>      Adding gr16 to data...already in plot data. Adding only to prediction data Ok
#>      Adding gr17 to data...already in plot data. Adding only to prediction data Ok
#>      Adding gr18 to data...already in plot data. Adding only to prediction data Ok
#>      Adding prec to data...already in plot data. Adding only to prediction data Ok
#>      Adding tmean to data...already in plot data. Adding only to prediction data Ok
#> 
#>   27 user defined maps added successfully!
#> 
#>  --------------------------
#>  Execution successful ! ! !
#>  --------------------------

The on-screen messages show you what happens during the execution of data2SDMaps2 and are self-explaining. A comment on the lines ‘Adding [variable] to data…’: if a covariate is already included to the plotdata (as is here the case for all but one covariate) they are only used to make the predgrid. For covariates that are not included to the plotdata (as is here the case for alt_categ) their values for the plotIDs are determined by an overlay with the corresponding grid file. Here, a short explanation of the used covariates:

Covariate code Explanation
alt_categ altitude in three classes
alt altitude
bio** bioclimatic variables
etp evapotranspiration
gr** CORINE land cover classes
prec annual precipitation
tmean annual mean temperature

By the way: alt_categ has only been used to show how categorical covariates have to be dealt with.

Next, check the output directory. Within directory “results” the directory “OBSERVATIONS” has been created, holding file lancol.DAT and another directory, “Temp1”, which holds the sdmdata file sdmdata.RDATA and file lancol.csv (which is not identical with lancol.csv that was used for data input). At first sight, this might appear as an excessively complicated structure, but it guarantees that with these sdmdata a series of different model runs for selected species or selected covariates can be performed without the necessity to prepare new specific data for each run.

Now inspect the structure of object sdmdata in the R workspace:

str(sdmdata, max.level = 2)
#> List of 11
#>  $ data          :Classes 'sf' and 'data.frame': 5493 obs. of  29 variables:
#>   ..$ plotID   : chr [1:5493] "AC25131" "AC251312" "AC251313" "AC251314" ...
#>   ..$ alt      : num [1:5493] 79 79 79 79 79 ...
#>   ..$ bio01    : num [1:5493] 110 110 110 110 110 110 110 110 110 110 ...
#>   ..$ bio05    : num [1:5493] 274 274 274 274 274 274 274 274 274 274 ...
#>   ..$ bio06    : num [1:5493] -41 -41 -41 -41 -41 ...
#>   ..$ bio12    : num [1:5493] 547 547 548 548 548 ...
#>   ..$ prec     : num [1:5493] 59 59 59 59 59 59 59 59 59 59 ...
#>   ..$ tmean    : num [1:5493] 155 155 155 155 155 155 155 155 155 155 ...
#>   ..$ etp      : num [1:5493] 9 9 9 9 9 9 9 9 9 9 ...
#>   ..$ gr01     : num [1:5493] 0 0 0 0 0 0 0 0 0 0 ...
#>   ..$ gr02     : num [1:5493] 0 0 0 0 0 0 0 0 0 0 ...
#>   ..$ gr03     : num [1:5493] 0 0 0 0 0 0 0 0 0 0 ...
#>   ..$ gr04     : num [1:5493] 1 0.5766 0.7273 0.6072 0.0195 ...
#>   ..$ gr05     : num [1:5493] 0 0 0 0 0 0 0 0 0 0 ...
#>   ..$ gr06     : num [1:5493] 0 0 0 0 0 0 0 0 0 0 ...
#>   ..$ gr07     : num [1:5493] 0 0 0 0 0 0 0 0 0 0 ...
#>   ..$ gr08     : num [1:5493] 0 0 0 0 0 0 0 0 0 0 ...
#>   ..$ gr09     : num [1:5493] 0 0 0 0 0.719 ...
#>   ..$ gr10     : num [1:5493] 0 0 0 0 0 0 0 0 0 0 ...
#>   ..$ gr11     : num [1:5493] 0 0 0 0 0 0 0 0 0 0 ...
#>   ..$ gr12     : num [1:5493] 0 0 0 0 0 0 0 0 0 0 ...
#>   ..$ gr13     : num [1:5493] 0 0 0 0 0 0 0 0 0 0 ...
#>   ..$ gr14     : num [1:5493] 0 0 0 0 0 0 0 0 0 0 ...
#>   ..$ gr15     : num [1:5493] 0 0 0 0 0 0 0 0 0 0 ...
#>   ..$ gr16     : num [1:5493] 0 0.423 0.273 0.393 0.261 ...
#>   ..$ gr17     : num [1:5493] 0 0 0 0 0 0 0 0 0 0 ...
#>   ..$ gr18     : num [1:5493] 0 0 0 0 0 0 0 0 0 0 ...
#>   ..$ geometry :sfc_POINT of length 5493; first list element:  'XY' num [1:2] 156960 514565
#>   ..$ alt_categ: Factor w/ 3 levels "0","500","1000": 1 1 1 1 1 1 1 1 1 1 ...
#>   ..- attr(*, "sf_column")= chr "geometry"
#>   ..- attr(*, "agr")= Factor w/ 3 levels "constant","aggregate",..: NA NA NA NA NA NA NA NA NA NA ...
#>   .. ..- attr(*, "names")= chr [1:28] "plotID" "alt" "bio01" "bio05" ...
#>  $ pred.data     :Classes 'sf' and 'data.frame': 4800 obs. of  28 variables:
#>   ..$ alt_categ: Factor w/ 4 levels "0","500","1000",..: 4 4 4 4 4 4 4 4 4 4 ...
#>   ..$ alt      : num [1:4800] NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ...
#>   ..$ bio01    : num [1:4800] NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ...
#>   ..$ bio05    : num [1:4800] NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ...
#>   ..$ bio06    : num [1:4800] NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ...
#>   ..$ bio12    : num [1:4800] NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ...
#>   ..$ etp      : num [1:4800] NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ...
#>   ..$ gr01     : num [1:4800] NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ...
#>   ..$ gr02     : num [1:4800] NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ...
#>   ..$ gr03     : num [1:4800] NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ...
#>   ..$ gr04     : num [1:4800] NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ...
#>   ..$ gr05     : num [1:4800] NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ...
#>   ..$ gr06     : num [1:4800] NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ...
#>   ..$ gr07     : num [1:4800] NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ...
#>   ..$ gr08     : num [1:4800] NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ...
#>   ..$ gr09     : num [1:4800] NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ...
#>   ..$ gr10     : num [1:4800] NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ...
#>   ..$ gr11     : num [1:4800] NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ...
#>   ..$ gr12     : num [1:4800] NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ...
#>   ..$ gr13     : num [1:4800] NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ...
#>   ..$ gr14     : num [1:4800] NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ...
#>   ..$ gr15     : num [1:4800] NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ...
#>   ..$ gr16     : num [1:4800] NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ...
#>   ..$ gr17     : num [1:4800] NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ...
#>   ..$ gr18     : num [1:4800] NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ...
#>   ..$ prec     : num [1:4800] NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ...
#>   ..$ tmean    : num [1:4800] NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ...
#>   ..$ geometry :sfc_POINT of length 4800; first list element:  'XY' num [1:2] 105760 795765
#>   ..- attr(*, "sf_column")= chr "geometry"
#>   ..- attr(*, "agr")= Factor w/ 3 levels "constant","aggregate",..: NA NA NA NA NA NA NA NA NA NA ...
#>   .. ..- attr(*, "names")= chr [1:27] "alt_categ" "alt" "bio01" "bio05" ...
#>  $ data.name     : chr "sdmdata"
#>  $ files         : chr "/data/Sovon/SDMaps2/Paketproduktion/SDMaps2/vignettes/results/OBSERVATIONS/Temp1"
#>  $ Userdir       : chr "/data/Sovon/SDMaps2/Paketproduktion/SDMaps2/vignettes/grids10km"
#>  $ n.unique.plots: int 5493
#>  $ specnames     : chr "lancol.DAT"
#>  $ not_run       : logi FALSE
#>  $ not_run_errors: logi FALSE
#>  $ call          : language data2SDMaps2(plot.data = "lancol.csv", crs = crs, outdir = file.path(getwd(),      "results"), grids.dir = file.p| __truncated__ ...
#>  $ attrs         :List of 1
#>   ..$ generated.zeroes: logi FALSE
#>  - attr(*, "SDMdata")= logi TRUE

As reported, it is a list consisting of 11 elements. The first two elements ($ data and $ pred.data) are simple features with geometry POINT, a class representing spatial data (Pebesma 2018), of the plot data and the maps used for prediction. The other elements save names, paths, the call with which data2SDMaps2 was invoked and some additional data information. With sdmdata in the workspace we can immediately proceed to a model run. However, it is wise to explore the data prior to modelling. We will do this in the next chapter.

Explore the data

Data exploration is a crucial step in every modelling attempt, because rubbish input produces rubbish output. Outliers, heterogeneity of variance, collinearity, dependence of observations etc. may cause serious problems dependent on the chosen modelling technique. In SDMmaps2, thus, function dataExploration2 checks for a series of potential violations of the underlying assumptions relevant for the employed statistical procedure, based on the protocol suggested by Zuur, Ieno, and Elphick (2010). Run function dataExploration2, below we will discuss it line by line:

In the output directory you find the following files (in chronological order produced during the data exploration process):

Make an SDM with SDMaps2

SDMaps2 is the central function of package SDMaps2. It also has a large number of arguments which you can use to specify a large range of different modelling runs. Here, however, we will begin with the most basic analyses, needing only a very few arguments. Below we will explain the call line by line.

In line 1 we invoke the function and save its output to object sdm.ranger.presence in the workspace. You can run SDMaps2 without saving a workspace object but this will be useful for the SDMapsSummary2 command below (section.

In line 2 we tell SDMaps2 which sdmdata to use (here, object sdmdata in the R workspace).

In line 3 we define the model type. Here, we specify that the SDM must be made with the random forest algorithm ranger. Actually, this is not necessary because ranger is the default modelling technique anyway, but we state it for clarity.

Line 4: Although regarded as one of the best available machine learning methods, random forests results are biased and tend to overestimate low values and to underestimate high values (Zhang and Lu 2012; Song 2015). By default this argument is set to TRUE anyway, for clarity we explicitly set it to TRUE here. Actually the correction has been implemented to correct count models, but it also works fine for presence models (as you will see soon).

In line 5 we specify that the data should be used as presence-absence data. In this case, all values > 0 are changed to 1.

The output directory is defined in line 6: we want a directory “ranger” to be generated within the output directory already defined for function data2SDMaps2; directory “ranger” in turn contains a directory “presence_absence”.

In line 7 we skip a variable from the analysis with argument vars.subs. This argument waits for a character vector of covariate names that should be used or skipped in the modelling run. For example, vars.subs = c(“alt”, ”bio01”) includes only covariates alt and bio01; vars.subs = c(“-gr10”, “-gr11”) uses all covariates except gr10 and gr11. You cannot mix using and skipping mode of vars.subs! For example, vars.subs = c(“bio01”, ”-gr11”) makes no sense and would cause the modelling run to stop with an error message! If left unspecified, all covariates will be included. The predictor variables defined in vars.subs will be used for all species in the modelling run.

SDMaps2 saves a lot of information in the output directory and in various formats, among others as text files. This makes it easier to use the output in other programmes but also can lead to rather bulky output. That is why by default no text files are saved. Here, we determine in line 8 that all text files be saved in the output directory.

In lines 9 and 10 we provide information where to find the contour file and the speciesnames file. You encountered these arguments already in function dataExploration.

You see the screen messages that report that SDMaps2 first checks the data, makes a copy of the analysis object in the output directory (handy if your modelling run includes more than one species and crashes; the species already run until the crash do not have to be modelled again), stores the sdmdata in a filehash database, proceeds to running the model, applies the bias correction procedure, and finally produces the maps, followed (hopefully) be a success message and the information where the results have been stored. Go to the results directory and check its contents!

First, you will find a directory called “RESULTS” in directory “ranger/presence_absence”. When you run SDMaps2 again–perhaps you want to use another selection of covariates–and do not change the specifications of argument out.dir, then its results will be stored in a new directory called “RESULTS1”. If you do repeated modelling runs, directories “RESULTS2”, “RESULTS3”, and so on, will be created. Anyhow SDMaps2 informs you where the ouput has been stored and displays a corresponding message.

Now look at the contents of “RESULTS”! First notice the naming conventions used for all the files. Since we provided the textfile speciesnames.txt, the species code could be complemented by the full (here, the scientific) species name. Files that store modelling information also include the used model type (here, ranger); maps include information what type of data they display (predicted, predictedr, int.resids). Let us go through them file by file, here listed in chronological order of creation during the modelling process.

Locations of observed presences (red) and absences (grey)

Locations of observed presences (red) and absences (grey)

Effect of ranger bias correction

Effect of ranger bias correction

Effect of ranger bias correction

Effect of ranger bias correction

Predicted probability of occurrence

Predicted probability of occurrence

Make a model summary with SDMapsSummary2

Getting some maps is not the whole modelling story. Of course you need some information on the modelling success, parameter estimates etc. You achieve this by the SDMapsSummary2 command which again knows a number of arguments:

With argument SDMres you specify the model for which you want to generate a summary. This can be an object resident in the workspace (we stored the output of command SDMaps2 in an object with the name sdm.ranger.presence). Alternatively, you can specify the path to the analysis object saved on the hard disk. In this case you use the argument

Replace the string RESULTS by RESULTS2, RESULTS3 etc. if necessary. (You remember that for each analysis run using the same output directory a new RESULTS subdirectory will be generated.)

With the remaining arguments–their defaults are FALSE–you specify which information you want to be displayed.

In the screen messages you see which calculations are being made and ist last line informs you where all the products have been saved. In chronological order of generation these are:

Partial dependence plots

Partial dependence plots

References

Ahmed, S.E., G. McInerny, K. O’Hara, R. Harper, L. Salido, S. Emmott, and L.N. Joppa. 2015. “Scientists and Software - Surveying the Species Distribution Modelling Community.” Diversity and Distributions 21: 258–67. https://doi.org/10.1111/ddi.12305.

Allouche, O., A. Tsoar, and R. Kadmon. 2006. “Assessing the Accuracy of Species Distribution Models: Prevalence, Kappa and the True Skill Statistic (Tss).” Journal of Applied Ecology 43: 1223–32. https://doi.org/10.1111/j.1365-2664.2006.01214.x.

Bivand, R.S., E. Pebesma, and V. Gómez-Rubio. 2013. Applied Spatial Data Analysis with R. Second. New York: Springer.

Chen, T., and C. Guestrin. 2016. “XGBoost: A Scalable Tree Boosting System.” In 22nd Sigkdd Conference on Knowledge Discovery and Data Mining, 2016. https://arxiv.org/abs/1603.02754.

Chen, T., T. He, M. Benesty, V. Khotilovich, Y. Tang, H. Cho, K. Chen, et al. 2021. Xgboost: Extreme Gradient Boosting. https://CRAN.R-project.org/package=xgboost.

Dormann, C.F., J.M. McPherson, M.B. Araújo, R. Bivand, J. Bolliger, G. Carl, R.G. Davies, et al. 2007. “Methods to Account for Spatial Autocorrelation in the Analysis of Species Distributional Data: A Review.” Ecography 30 (5): 609–28. https://doi.org/10.1111/j.2007.0906-7590.05171.x.

Freeman, E.A., and G. Moisen. 2008. “PresenceAbsence: An R Package for Presence Absence Analysis.” Journal of Statistical Software 23 (11): 1–31. http://www.jstatsoft.org/v23/i11.

Goldstein, A., A. Kapelner, J. Bleich, and E. Pitkin. 2015. “Peeking Inside the Black Box: Visualizing Statistical Learning with Plots of Individual Conditional Expectation.” Journal of Computational and Graphical Statistics 24(1): 44–65. https://doi.org/https://doi.org/10.1080/10618600.2014.907095.

Hengl, T., H. Sierdsema, A. Radović, and A. Dilo. 2009. “Spatial prediction of species’ distributions from occurrence-only records: combining point pattern analysis, ENFA and regression-kriging.” Ecological Modelling 220: 3499–3511. https://doi.org/10.1016/j.ecolmodel.2009.06.038.

Leroy, B., R. Delsol, B. Hugueny, C.N. Meynard, C. Barhoumi, M. Barbet-Massin, and C. Bellard. 2018. “Without Quality Presence-Absence Data, Discrimination Metrics Such as Tss Can Be Misleading Measures of Model Performance.” Journal of Biogeography 45: 1994–2002.

Liaw, A., and M. Wiener. 2002. “Classification and Regression by randomForest.” R News 2: 18–22. http://CRAN.R-project.org/doc/Rnews/.

Miles, J., and M. Shevlin. 2001. Applying Regression & Correlation - a Guide for Students and Researchers. London: Sage Publishers.

Pebesma, E.J. 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.

Song, J. 2015. “Bias Corrections for Random Forest in Regression Using Residual Rotation.” Journal of the Korean Statistical Society 44: 321–26. https://doi.org/10.1016/j.jkss.2015.01.003.

Wooldridge, J., and J. Stewart. 2015. Introductory Econometrics: A Modern Approach. 6th ed. Boston MA: Cengage Learning.

Wright, M.N., and A. Ziegler. 2017. “Ranger: A Fast Implementation of Random Forests for High Dimensional Data in C++ and R.” Journal of Statistical Software 77 (1): 1–17. https://doi.org/10.18637/jss.v077.i01.

Zhang, G., and Y. Lu. 2012. “Bias-Corrected Random Forests in Regression.” Journal of Applied Statistics 39: 151–60. https://doi.org/10.1080/02664763.2011.578621.

Zuur, A.F., E.N. Ieno, and C.S. Elphick. 2010. “A Protocol for Data Exploration to Avoid Common Statistical Problems.” Methods in Ecology & Evolution 1: 3–14. https://doi.org/10.1111/j.2041-210X.2009.00001.x.

Zuur, A., E. Ieno, N.J. Walker, A.A. Saveliev, and G.M. Smith. 2009. Mixed Effects Models and Extensions in Ecology with R. New York: Springer.