bioticVelocity: Velocity of shifts in densities across a series of rasters

View source: R/bioticVelocity.r

bioticVelocityR Documentation

Velocity of shifts in densities across a series of rasters

Description

This function calculates several metrics of biotic velocity for a stack of rasters or an array representing a gridded landscape.

Usage

bioticVelocity(
  x,
  times = NULL,
  atTimes = NULL,
  longitude = NULL,
  latitude = NULL,
  elevation = NULL,
  metrics = c("centroid", "nsCentroid", "ewCentroid", "nCentroid", "sCentroid",
    "eCentroid", "wCentroid", "nsQuants", "ewQuants", "similarity", "summary"),
  quants = c(0.05, 0.1, 0.5, 0.9, 0.95),
  onlyInSharedCells = FALSE,
  cores = 1,
  warn = TRUE,
  paths = NULL,
  ...
)

Arguments

x

Either a RasterStack, RasterBrick, or 3-dimensional array. Values should be either NA or >= 0.

  • If x is a RasterStack or RasterBrick then each layer is assumed to represent a time slice and the rasters must be in an equal-area projection.

  • If x is an array then each "layer" in the third dimension is assumed to represent a map at a particular time slice in an equal-area projection. Note that if this is an array you should probably also specify the arguments longitude and latitude.

times

Numeric vector with the same number of layers in x or NULL (default). This specifies the time represented by each layer in x from oldest (top layer) to most recent (bottom layer). Times must appear in sequential order. For example, if time periods are 24 kybp, 23 kybp, 22 kybp, use c(-24, -23, -22), not c(24, 23, 22). If NULL (default), values are assigned starting at 1 and ending at the total number of layers in x.

atTimes

Numeric, values of times across which to calculate biotic velocity. You can use this to calculate biotic velocities across selected time periods (e.g., just the first and last time periods). Note that atTimes must be the same as or a subset of times. The default is NULL, in which case velocity is calculated across all time slices (i.e., between times 1 and 2, 2 and 3, 3 and 4, etc.).

longitude

Numeric matrix or NULL (default):

  • If x is a RasterStack or RasterBrick then this is ignored (longitude is ascertained directly from the rasters, which must be in equal-area projection for velocities to be valid).

  • If x is an array and longitude is NULL (default), then longitude will be ascertained from column numbers in x and velocities will be in arbitrary spatial units (versus, for example, meters). Alternatively, this can be a two-dimensional matrix whose elements represent the longitude coordinates of the centers of cells of x. The matrix must have the same number of rows and columns as x. Coordinates must be from an equal-area projection for results to be valid.

latitude

Numeric matrix or NULL (default):

  • If x is a RasterStack or RasterBrick then this is ignored (latitude is obtained directly from the rasters, which must be in equal-area projection for velocities to be valid).

  • If x is an array and latitude is NULL (default), then latitude will be obtained from row numbers in x and velocities will be in arbitrary spatial units (versus, for example, meters). Alternatively, this can be a two-dimensional matrix whose elements represent the latitude coordinates of the centers of cells of x. The matrix must have the same number of rows and columns as x. Coordinates must be from an equal-area projection for results to be valid.

elevation

Either NULL (default) or a raster or matrix representing elevation. If this is supplied, changes in elevation are incorporated into all velocity and speed metrics. Additionally, you can also calculate the metrics elevCentrioid and elevQuants.

metrics

Biotic velocity metrics to calculate (default is to calculate them all). All metrics ignore NA cells in x. Here "starting time period" represents one layer in x and "end time period" the next layer.

  • summary: This calculates a series of measures, none of which are measures of velocity:

    • Mean: Mean value across all cells.

    • Sum: Total across all cells.

    • Quantiles: Nth quantile values across all cells. Quantiles are given by quants.

    • Prevalence: Number of cells with values > 0.

  • centroid: Speed of mass-weighted centroid.

  • nsCentroid or ewCentroid: Velocity in the north-south or east-west directions of the mass-weighted centroid. For north-south cardinality, positive values represent movement northward and negative southward.

  • nCentroid, sCentroid, eCentroid, and wCentroid: Speed of mass-weighted centroid of the portion of the raster north/south/east/west of the landscape-wide weighted centroid of the starting time period.

  • nsQuants or ewQuants: Velocity of the location of the Nth quantile of mass in the north-south or east-west directions. The quantiles can be specified in quants. For example, this could be the movement of the 5th, 50th, and 95th quantiles of population size going from south to north. The 0th quantile would measure the velocity of the southernmost or easternmost cell(s) with values >0, and the 100th quantile the northernmost or westernmost cell(s) with non-zero values.

  • similarity: Several metrics of similarity between each time period. Some of these make sense only for cases where values in x are in the range [0, 1], but not if some values are outside this range. See compareNiches for more details. The metrics are:

    • Simple mean difference

    • Mean absolute difference

    • Root-mean squared difference

    • Expected Fraction of Shared Presences or ESP (Godsoe 2014)

    • D statistic (Schoener 1968)

    • I statistic (Warren et al. 2008)

    • Pearson correlation

    • Spearman rank correlation

  • elevCentroid: Velocity of the centroid of mass in elevation (up or down). Argument elevation must be supplied.

  • elevQuants: Velocity of the emphnth quantile of mass in elevation (up or down). The quantiles to be evaluated are given by quants. The lowest elevation with mass >0 is the 0th quantile, and the highest elevation with mass >0 is the 100th. Argument elevation must be supplied.

quants

Numeric vector indicating the quantiles at which biotic velocity is calculated for the "quant" and "Quants" metrics. Default is c(0.05, 0.10, 0.5, 0.9, 0.95).

onlyInSharedCells

Logical, if TRUE, calculate biotic velocity using only those cells that are not NA in the start and end of each time period. This is useful for controlling for shifting land mass due to sea level rise, for example, when calculating biotic velocity for an ecosystem or a species. The default is FALSE.

cores

Positive integer. Number of processor cores to use. Note that if the number of time steps at which velocity is calculated is small, using more cores may not always be faster.

warn

Logical, if TRUE (default) then display function-specific warnings.

paths

Character vector or NULL (default). This is used internally for multi-core functionality and so rarely by the user (i.e., leave this as NULL).

...

Other arguments (not used).

Details

Attention:

This function may yield erroneous velocities if the region of interest is near or spans a pole or the international date line. Results using the "Quant" and "quant" metrics may be somewhat counterintuitive if just one cell is >0, or one row or column has the same values with all other values equal to 0 or NA because defining quantiles in these situations is not intuitive. Results may also be counterintuitive if some cells have negative values because they can "push" a centroid away from what would seem to be the center of mass as assessed by visual examination of a map.

Note:

For the nsQuants and ewQuants metrics it is assumed that the latitude/longitude assigned to a cell is at its exact center. If a desired quantile does not fall exactly on the cell center, it is interpolated linearly between the rows/columns of cells that bracket the given quantile. For quantiles that fall south/westward of the first row/column of cells, the cell border is assumed to be at 0.5 * cell length south/west of the cell center.

Value

A data frame with biotic velocities and related values. Fields are as follows:

  • timeFrom: Start time of interval

  • timeTo: End time of interval

  • timeSpan: Duration of interval

Depending on metrics that are specified, additional fields are as follows. All measurements of velocity are in distance units (typically meters) per time unit (which is the same as the units used for times and atTimes). For example, if the rasters are in an Albers equal-area projection and times are in years, then the output will be meters per year.

  • If metrics contains summary:

    • A column named propSharedCellsNotNA: Proportion of cells that are not NA in both the "from" and "to" time step.

    • Columns named timeFromPropNotNA and timeToPropNotNA: Proportion of cells in the "from" time and "to" steps that are not NA.

    • A column named mean: Mean weight in "timeTo" time step. In the same units as the values of the cells.

    • Columns named quantile_quantN: The Nth quantile(s) of weight in the "timeTo" time step. In the same units as the values of the cells.

    • A column named prevalence: Proportion of non-NA cells with weight >0 in the "timeTo" time step relative to all non-NA cells. Unitless.

  • If metrics has 'centroid': Columns named centroidVelocity, centroidLong, centroidLat – Speed of weighted centroid, plus its longitude and latitude (in the "to" time period of each time step). Values are always >= 0.

  • If metrics has 'nsCentroid': Columns named nsCentroid and nsCentroidLat – Velocity of weighted centroid in north-south direction, plus its latitude (in the "to" time period of each time step). Positive values connote movement north, and negative values south.

  • If metrics has 'ewControid': ewCentroid and ewCentroidLong – Velocity of weighted centroid in east-west direction, plus its longitude (in the "to" time period of each time step). Positive values connote movement east, and negative values west.

  • If metrics has 'nCentroid', 'sCentroid', 'eCentroid', and/or 'wCentroid': Columns named nCentroidVelocity and nCentroidAbund, sCentroid and sCentroidAbund, eCentroid and eCentroidAbund, and/or wCentroid and wCentroidAbund – Speed of weighted centroid of all cells that fall north, south, east, or west of the landscape-wide centroid, plus a column indicating the weight (abundance) of all such populations. Values are always >= 0.

  • If metrics contains any of nsQuants or ewQuants: Columns named nsQuantVelocity_quantN and nsQuantLat_quantN, or ewQuantVelocity_quantN and ewQuantLat_quantN: Velocity of the Nth quantile weight in the north-south or east-west directions, plus the latitude or longitude thereof (in the "to" time period of each time step). Quantiles are cumulated starting from the south or the west, so the 0.05th quantile, for example, is in the far south or west of the range and the 0.95th in the far north or east. Positive values connote movement north or east, and negative values movement south or west.

  • If metrics contains similarity, metrics of similarity are calculated for each pair of successive landscapes, defined below as x1 and x2, with the number of shared non-NA cells between them being n:

    • A column named simpleMeanDiff: sum(x2 - x1, na.rm=TRUE) / n

    • A column named meanAbsDiff: sum(abs(x2 - x1), na.rm=TRUE) / n

    • A column named rmsd (root-mean square difference): sqrt(sum((x2 - x1)^2, na.rm=TRUE)) / n

    • A column named godsoeEsp: 1 - sum(2 * (x1 * x2), na.rm=TRUE) / sum(x1 + x2, na.rm=TRUE), values of 1 ==> maximally similar, 0 ==> maximally dissimilar.

    • A column named schoenersD: 1 - (sum(abs(x1 - x2), na.rm=TRUE) / n), values of 1 ==> maximally similar, 0 ==> maximally dissimilar.

    • A column named warrensI: 1 - sqrt(sum((sqrt(x1) - sqrt(x2))^2, na.rm=TRUE) / n), values of 1 ==> maximally similar, 0 ==> maximally dissimilar.

    • A column named cor: Pearson correlation between values of x1 and x2.

    • A column named rankCor: Spearman rank correlation between values of x1 and x2.

  • If metrics contains elevCentroid: Columns named elevCentroidVelocity and elevCentroidElev – Velocity of the centroid in elevation (up or down) and the elevation in the "to" timestep. Positive values of velocity connote movement upward, and negative values downward.

  • If metrics contains elevQuants: Columns named elevQuantVelocity_quantN and elevQuantVelocityElev_quantN – Velocity of the Nth quantile of mass in elevation (up or down) and the elevation of this quantile in the "to" timestep. Positive values of velocity connote movement upward, and negative values downward.

Examples

## Not run: 
library(raster)

### movement in north-south directions
mat <- matrix(0, nrow=5, ncol=5)
mat1 <- mat2 <- mat
mat1[3, 3] <- 1
mat2[2, 3] <- 1

mats <- array(c(mat1, mat2), dim=c(nrow(mat1), ncol(mat1), 2))
rownames(mats) <- paste0('lat', nrow(mats):1)
colnames(mats) <- paste0('long', 1:ncol(mats))
lats <- matrix(nrow(mats):1, nrow=nrow(mats), ncol=ncol(mats))
longs <- matrix(1:nrow(mats), nrow=nrow(mats), ncol=ncol(mats), byrow=TRUE)

mat1rast <- raster(mat1)
mat2rast <- raster(mat2)
matsRast <- stack(mat1rast, mat2rast)
plot(matsRast, col=c('gray', 'darkgreen'))

# note that nCentroidVelocity is NaN because just one cell is occupied
(bioticVelocity(mats, times=1:2,
latitude=lats, longitude=longs)) # north movement
(bioticVelocity(mats[ , , 2:1], times=1:2,
latitude=lats, longitude=longs)) # south movement


### movement in east-west directions
mat <- matrix(0, nrow=5, ncol=5)
mat1 <- mat2 <- mat
mat1[3, 3] <- 1
mat2[3, 2] <- 1

mats <- array(c(mat1, mat2), dim=c(nrow(mat1), ncol(mat1), 2))
rownames(mats) <- paste0('lat', nrow(mats):1)
colnames(mats) <- paste0('long', 1:ncol(mats))
lats <- matrix(nrow(mats):1, nrow=nrow(mats), ncol=ncol(mats))
longs <- matrix(1:nrow(mats), nrow=nrow(mats), ncol=ncol(mats), byrow=TRUE)

mat1rast <- raster(mat1)
mat2rast <- raster(mat2)
matsRast <- stack(mat1rast, mat2rast)
plot(matsRast, col=c('gray', 'darkgreen'))

# movement east
(bioticVelocity(mats, times=1:2,
latitude=lats, longitude=longs))

# movement west
(bioticVelocity(mats[ , , 2:1], times=1:2,
latitude=lats, longitude=longs))


### movement of portions of range northward/southward
mat <- matrix(0, nrow=11, ncol=11)
mat1 <- mat2 <- mat
mat1[6, 5] <- 1 # bottom
mat1[5, 5] <- 1 # center
mat1[5, 4] <- 1 # west
mat1[5, 6] <- 1 # east
mat1[4, 5] <- 1 # north

mat2[6, 5] <- 1 # bottom
mat2[5, 5] <- 1 # center
mat2[5, 4] <- 1 # west
mat2[5, 6] <- 1 # east
mat2[3, 5] <- 1 # north

mats <- array(c(mat1, mat2), dim=c(nrow(mat1), ncol(mat1), 2))
rownames(mats) <- paste0('lat', nrow(mats):1)
colnames(mats) <- paste0('long', 1:ncol(mats))
lats <- matrix(nrow(mats):1, nrow=nrow(mats), ncol=ncol(mats))
longs <- matrix(1:nrow(mats), nrow=nrow(mats), ncol=ncol(mats), byrow=TRUE)

mat1rast <- raster(mat1)
mat2rast <- raster(mat2)
matsRast <- stack(mat1rast, mat2rast)
plot(matsRast, col=c('gray', 'darkgreen'))

# northern section moves north
(bioticVelocity(mats, times=1:2,
latitude=lats, longitude=longs))
# northern section moves south
(bioticVelocity(mats[ , , 2:1], times=1:2,
latitude=lats, longitude=longs))

### quantile velocities: north/south movement
mat <- matrix(0, nrow=11, ncol=11)
mat1 <- mat2 <- mat

mat1[2:10, 6] <- 1
mat2[1:9, 6] <- 1

mats <- array(c(mat1, mat2), dim=c(nrow(mat1), ncol(mat1), 2))
rownames(mats) <- paste0('lat', nrow(mats):1)
colnames(mats) <- paste0('long', 1:ncol(mats))
lats <- matrix(nrow(mats):1, nrow=nrow(mats), ncol=ncol(mats))
longs <- matrix(1:nrow(mats), nrow=nrow(mats), ncol=ncol(mats), byrow=TRUE)

mat1rast <- raster(mat1)
mat2rast <- raster(mat2)
matsRast <- stack(mat1rast, mat2rast)
plot(matsRast, col=c('gray', 'darkgreen'))

# shift north
(bioticVelocity(mats, times=1:2,
latitude=lats, longitude=longs))
# shift south
(bioticVelocity(mats[ , , 2:1], times=1:2,
latitude=lats, longitude=longs))


### quantile velocities: east/west movement
mat <- matrix(0, nrow=11, ncol=11)
mat1 <- mat2 <- mat

mat1[6, 2:10] <- 1
mat2[6, 3:11] <- 1

mats <- array(c(mat1, mat2), dim=c(nrow(mat1), ncol(mat1), 2))
rownames(mats) <- paste0('lat', nrow(mats):1)
colnames(mats) <- paste0('long', 1:ncol(mats))
lats <- matrix(nrow(mats):1, nrow=nrow(mats), ncol=ncol(mats))
longs <- matrix(1:nrow(mats), nrow=nrow(mats), ncol=ncol(mats), byrow=TRUE)

mat1rast <- raster(mat1)
mat2rast <- raster(mat2)
matsRast <- stack(mat1rast, mat2rast)
plot(matsRast, col=c('gray', 'darkgreen'))

# eastward shift
(bioticVelocity(mats, times=1:2,
latitude=lats, longitude=longs))
# westward shift
(bioticVelocity(mats[ , , 2:1], times=1:2,
latitude=lats, longitude=longs))

### big block test
mat <- matrix(0, nrow=7, ncol=7)
mat1 <- mat2 <- mat

mat1[3:5, 3:5] <- 1
mat2[1:3, 1:3] <- 1

mats <- array(c(mat1, mat2), dim=c(nrow(mat1), ncol(mat1), 2))
rownames(mats) <- paste0('lat', nrow(mats):1)
colnames(mats) <- paste0('long', 1:ncol(mats))
lats <- matrix(nrow(mats):1, nrow=nrow(mats), ncol=ncol(mats))
longs <- matrix(1:nrow(mats), nrow=nrow(mats), ncol=ncol(mats), byrow=TRUE)

mat1rast <- raster(mat1)
mat2rast <- raster(mat2)
matsRast <- stack(mat1rast, mat2rast)
plot(matsRast, col=c('gray', 'darkgreen'))

# shift northwest
(bioticVelocity(mats, times=1:2,
latitude=lats, longitude=longs))
# shift southeast
(bioticVelocity(mats[ , , 2:1], times=1:2,
latitude=lats, longitude=longs))


### big block test: common frame
mat <- matrix(0, nrow=7, ncol=7)
mat1 <- mat2 <- mat

mat1[3:5, 3:5] <- 1
mat1[1, ] <- NA
mat1[ , 1] <- NA
mat2[1:3, 1:3] <- 1

mats <- array(c(mat1, mat2), dim=c(nrow(mat1), ncol(mat1), 2))
rownames(mats) <- paste0('lat', nrow(mats):1)
colnames(mats) <- paste0('long', 1:ncol(mats))
lats <- matrix(nrow(mats):1, nrow=nrow(mats), ncol=ncol(mats))
longs <- matrix(1:nrow(mats), nrow=nrow(mats), ncol=ncol(mats), byrow=TRUE)

mat1rast <- raster(mat1)
mat2rast <- raster(mat2)
matsRast <- stack(mat1rast, mat2rast)
plot(matsRast, col=c('gray', 'darkgreen'))

v1 <- bioticVelocity(mats, times=1:2,
latitude=lats, longitude=longs)
v2 <- bioticVelocity(mats, times=1:2,
latitude=lats, longitude=longs, onlyInSharedCells=TRUE)
(rbind(v1, v2))

### elevation
# first case: all elevations the same, abundance moves north
n <- 5
mat <- matrix(NA, nrow=n, ncol=n)
mat1 <- mat
mat1[c(1, 5), ] <- 0
mat1[c(2, 4), ] <- 1
mat1[c(3), ] <- 3

mat2 <- mat
mat2[c(4, 5), ] <- 0
mat2[c(1, 3), ] <- 1
mat2[c(2), ] <- 3

lat <- matrix(rep(n:1, n), nrow=n)
long <- matrix(rep(1:n, each=n), nrow=n)

mats <- array(c(mat1, mat2), dim=c(n, n, 2))
colnames(mats) <- paste0('long', long[1, ])
rownames(mats) <- paste0('lat', lat[ , 1])

elev1 <- mat
elev1[] <- 1

metrics <- c('centroid', 'elevCentroid')
bv1 <- bioticVelocity(x=mats, longitude=long, latitude=lat, metrics=metrics,
elevation=elev1)

# second case: elevations higher in "northern" portion, abundance moves north
elev2 <- mat
elev2[] <- 1
elev2[1:2, ] <- 2
bv2 <- bioticVelocity(x=mats, longitude=long, latitude=lat, metrics=metrics,
elevation=elev2)

rbind(bv1, bv2)

## End(Not run)

## Not run: 
### multi-core
mats <- array(runif(100 * 100 * 1000), dim=c(100, 100, 500))
mats <- brick(mats)
projection(mats) <- getCRS('wgs84')

# adding elevation increases velocity because it increases average
# distance between cells
elev <- matrix(rnorm(100 * 100, 0, 0.1), nrow=100)
elev <- raster(elev, crs=getCRS('wgs84'))

mc1 <- bioticVelocity(x=mats, metrics='centroid', cores=4)
mc2 <- bioticVelocity(x=mats, elevation=elev, metrics='centroid', cores=4)
plot(mc1$centroidVelocity, mc2$centroidVelocity,
xlab='Velocity: No elevation', ylab='Velocity: Elevation')
abline(0, 1)

## End(Not run)


adamlilith/enmSdm documentation built on Jan. 6, 2023, 11 a.m.