3. Absence and background points¶
Some of the early species distribution model algorithms, such as Bioclim and Domain only use ‘presence’ data in the modeling process. Other methods also use ‘absence’ data or ‘background’ data. Logistic regression is the classical approach to analyzing presence and absence data (and it is still much used, often implemented in a generalized linear modeling (GLM) framework). If you have a large dataset with presence/absence from a well designed survey, you should use a method that can use these data (i.e. do not use a modeling method that only considers presence data). If you only have presence data, you can still use a method that needs absence data, by substituting absence data with background data.
Background data (e.g. Phillips et al. 2009) are not attempting to guess at absence locations, but rather to characterize environments in the study region. In this sense, background is the same, irrespective of where the species has been found. Background data establishes the environmental domain of the study, whilst presence data should establish under which conditions a species is more likely to be present than on average. A closely related but different concept, that of “pseudo-absences”, is also used for generating the non-presence class for logistic models. In this case, researchers sometimes try to guess where absences might occur – they may sample the whole region except at presence locations, or they might sample at places unlikely to be suitable for the species. We prefer the background concept because it requires fewer assumptions and has some coherent statistical methods for dealing with the “overlap” between presence and background points (e.g. Ward et al. 2009; Phillips and Elith, 2011).
Survey-absence data has value. In conjunction with presence records, it establishes where surveys have been done, and the prevalence of the species given the survey effort. That information is lacking for presence-only data, a fact that can cause substantial difficulties for modeling presence-only data well. However, absence data can also be biased and incomplete, as discussed in the literature on detectability (e.g., Kéry et al., 2010).
dismo package has a function to sample random points (background
data) from a study area. You can use a ‘mask’ to exclude area with no
NA, e.g. areas not on land. You can use an ‘extent’ to further
restrict the area from which random locations are drawn.
In the example below, we first get the list of filenames with the
predictor raster data (discussed in detail in the next chapter). We use
a raster as a ‘mask’ in the
randomPoints function such that the
background points are from the same geographic area, and only for places
where there are values (land, in our case).
Note that if the mask has the longitude/latitute coordinate reference
randomPoints selects cells according to cell area,
which varies by latitude (as in Elith et al., 2011)
library(dismo) # get the file names files <- list.files(path=paste(system.file(package="dismo"), '/ex', sep=''), pattern='grd', full.names=TRUE ) # we use the first file to create a RasterLayer mask <- raster(files) # select 500 random points # set seed to assure that the examples will always # have the same random sample. set.seed(1963) bg <- randomPoints(mask, 500 )
And inspect the results by plotting
# set up the plotting area for two maps par(mfrow=c(1,2)) plot(!is.na(mask), legend=FALSE) points(bg, cex=0.5) # now we repeat the sampling, but limit # the area of sampling using a spatial extent e <- extent(-80, -53, -39, -22) bg2 <- randomPoints(mask, 50, ext=e) plot(!is.na(mask), legend=FALSE) plot(e, add=TRUE, col='red') points(bg2, cex=0.5)
There are several approaches one could use to sample ‘pseudo-absence’
points, i.e., points from more restricted area than ‘background’.
VanDerWal et al. (2009) sampled withn a radius of presence points. Here
is one way to implement that, using the
Solanum acaule data.
We first read the cleaned and subsetted
S. acaule data that we
produced in the previous chapter from the csv file that comes with
file <- paste(system.file(package="dismo"), '/ex/acaule.csv', sep='') ac <- read.csv(file)
ac is a
data.frame. Let’s change it into a
coordinates(ac) <- ~lon+lat projection(ac) <- CRS('+proj=longlat +datum=WGS84')
We first create a ‘circles’ model (see the chapter about geographic models), using an arbitrary radius of 50 km
# circles with a radius of 50 km x <- circles(ac, d=50000, lonlat=TRUE) ## Loading required namespace: rgeos pol <- polygons(pol) ## Error in polygons(pol): object 'pol' not found
Note that you need to have the
rgeos package installed for the
circles function to ‘dissolve’ the circles (remove boundaries were
And then we take a random sample of points within the polygons. We only want one point per grid cell.
# sample randomly from all circles samp1 <- spsample(pol, 250, type='random', iter=25) ## Error in spsample(pol, 250, type = "random", iter = 25): object 'pol' not found # get unique cells cells <- cellFromXY(mask, samp1) ## Error in cellFromXY(mask, samp1): object 'samp1' not found length(cells) ## Error in eval(expr, envir, enclos): object 'cells' not found cells <- unique(cells) ## Error in unique(cells): object 'cells' not found length(cells) ## Error in eval(expr, envir, enclos): object 'cells' not found xy <- xyFromCell(mask, cells) ## Error in .doXYFromCell(object@ncols, object@nrows, e@xmin, e@xmax, e@ymin, : object 'cells' not found
Plot to inspect the results:
plot(pol, axes=TRUE) ## Error in plot(pol, axes = TRUE): object 'pol' not found points(xy, cex=0.75, pch=20, col='blue') ## Error in points(xy, cex = 0.75, pch = 20, col = "blue"): object 'xy' not found
Note that the blue points are not all within the polygons (circles), as they now represent the centers of the selected cells from mask. We could choose to select only those cells that have their centers within the circles, using the overlay function.
spxy <- SpatialPoints(xy, proj4string=CRS('+proj=longlat +datum=WGS84')) ## Error in coordinates(coords): object 'xy' not found o <- over(spxy, geometry(x)) ## Error in over(spxy, geometry(x)): object 'spxy' not found xyInside <- xy[!is.na(o), ] ## Error in eval(expr, envir, enclos): object 'xy' not found
Similar results could also be achieved via the raster functions
# extract cell numbers for the circles v <- extract(mask, x@polygons, cellnumbers=T) # use rbind to combine the elements in list v v <- do.call(rbind, v) # get unique cell numbers from which you could sample v <- unique(v[,1]) head(v) ##  15531 15717 17581 17582 17765 17767 # to display the results m <- mask m <- NA m[v] <- 1 plot(m, ext=extent(x@polygons)+1) plot(x@polygons, add=T)