LBI tutorial

Pierre Denelle & Pieter Sanczuk

2025-10-21


LBI stands for Latitudinal Bias Index.


The following R packages are required to build this vignette:

library("latbias")
library("sf")
library("elevatr")
library("rnaturalearth")



1. Latitudinal Bias Index (LBI)

The LBI, representing the probability to detect more pronounced latitudinal rather than longitudinal range shifts due to the polygon geometry.
It is calculated as the odd-ratio of latitudinal and longitudinal distances, following this equation:

\[LBI = 2\times(\frac{mean(|\frac{A_nlat}{A_nlon}|)}{1+mean(|\frac{A_nlat}{A_nlon}|)}-0.5)\]

with \(A_nlat\) and \(A_nlon\) denoting the geographic displacement of the centroid positions of both sets of observation in the \(n^{th}\) iteration by means in the latitudinal and the longitudinal dimension.

An LBI value of zero represents a perfect balanced study design, meaning that the likelihood to record more pronounced latitudinal range shifts due to the study area geometry is 0%. By contrast, an LBI value of +1 denotes a 100% probability to exclusively record latitudinal shifts as would be the case for range shift data recorded along a perfectly South-North oriented straight line, whereas and an LBI value of -1 indicates a 100% probability to exclusively record longitudinal shifts as would be the case for range shift data recorded along a perfectly East-West oriented straight line.

2. Computing the LBI

We first take the polygon delineating Sweden as an example.

study_area <- rnaturalearth::ne_countries(scale = 50, continent = "Europe",
                                          country = "Sweden", type = "map_units", returnclass = "sf")
study_area <- sf::st_union(study_area)

We then calculate the LBI with the shape of Sweden.

lbi_sweden <-
  LBI(study_area_id = "Sweden", study_area_polygon = study_area,
      nobs = 10, nboot = 50, fact_location = 5, elevation = NULL)

lbi_sweden

In addition to the geographic distance between sampled points, we can also include the difference in terms of elevation. An unprojected raster can be added with teh argument elevation in the function LBI().

# With elevation
elevation_df <- elevatr::get_elev_raster(locations = st_as_sf(study_area),
                                         z = 5)

lbi_elev <- LBI(study_area_id = "Sweden", study_area_polygon = study_area,
                nobs = 10, nboot = 10, fact_location = 5,
                elevation = elevation_df)


3. Plotting one windrose

The argument raw_output allows the LBI function to return all bootstraps results.

lbi_sweden_all <-
  LBI(study_area_id = "Sweden", study_area_polygon = study_area,
      nobs = 10, nboot = 50, fact_location = 5, elevation = NULL,
      raw_output = TRUE)

We can then select the raw results and plot the direction and speed of all observed shifts, using the function windrose().

test <- as.data.frame(
  lbi_sweden_all$all[, c("study_area_id", "distance_km",
                         "bearing", "rep")])
test$distance_km <- as.numeric(test$distance_km)
windrose(data = test, spd = "distance_km", dir = "bearing")

4. References

When using the LBI R package, please cite the following reference:

Sanczuk, P., Lenoir, J., Denelle, P., Rumpf, S.B., Borderieux, J., Geppert, C., Oliveira, B.F. & Staude, I.R. Global bias towards recording latitudinal range shifts. submitted