Overview
This code has been written to simplify the process for running a prioritizr analysis on a given region. It is still a work in progress so feel free to submit pull requests with new features and code improvements.
Set user parameters
You can set a region if it is defined in
splnr_get_planningUnits
.
Region <- "Coral Sea" # "Australia"
Type <- "Oceans" # "EEZ"
You can also define a region with square boundaries (in degrees) if you need.
Region <- c(xmin = 150, xmax = 160, ymin = -40, ymax = -30)
Choose CRS for analysis. In this case we use Mollweide
cCRS <- "ESRI:54009"
Set the diameter of the planning units. This will be in the same units as the CRS (usually metres or degrees).
PU_size <- 107460 # m
Analysis Region
Start your analysis by defining your region and setting up the planning units.
Get the boundary for your chosen region.
Bndry <- splnr_get_boundary(Limits = Region, Type = Type, cCRS = cCRS)
#> Reading layer `ne_10m_geography_marine_polys' from data source
#> `/private/var/folders/_r/mcmw_qtn0m7cd23cbdqfszl40000gp/T/RtmpFXGTcW/ne_10m_geography_marine_polys.shp'
#> using driver `ESRI Shapefile'
#> Simple feature collection with 306 features and 37 fields
#> Geometry type: MULTIPOLYGON
#> Dimension: XY
#> Bounding box: xmin: -180 ymin: -85.19206 xmax: 179.9999 ymax: 90
#> Geodetic CRS: WGS 84
Get the land boundaries to remove overlap. The object “landmass” represents the land mass that should be removed (inverse = FALSE)
landmass <- rnaturalearth::ne_countries(
scale = "medium",
returnclass = "sf"
) %>%
sf::st_transform(cCRS)
Create Planning Units
PUs <- spatialgridr::get_grid(boundary = Bndry,
crs = cCRS,
output = "sf_hex",
resolution = PU_size)
We can check what the PUs look like
(ggPU <- splnr_plot(df = PUs) +
ggplot2::theme_bw()) # Plot Planning Units
If we want to add additional properties to our map, for example
landmass or the boundary, we can use splnr_gg_add()
.
(ggPU <- splnr_plot(df = PUs) +
splnr_gg_add(
Bndry = Bndry, overlay = landmass,
cropOverlay = PUs, ggtheme = "Default"
))
We can also use a customised ggplpot
theme that can be
passed as a list to splnr_gg_add()
and that can then be
used for all plots. For example:
splnr_theme <- list(
ggplot2::theme_bw(),
ggplot2::theme(
legend.position = "right",
legend.direction = "vertical",
text = ggplot2::element_text(size = 9, colour = "black"),
axis.text = ggplot2::element_text(size = 9, colour = "black"),
plot.title = ggplot2::element_text(size = 9),
axis.title = ggplot2::element_blank()
)
)
(ggPU <- splnr_plot(PUs) +
splnr_gg_add(
Bndry = Bndry, overlay = landmass,
cropOverlay = PUs, ggtheme = splnr_theme
))
Get the features
For our example, we will use a small subset of charismatic megafauna species of the Coral Sea to inform the conservation plan. We filtered the Aquamaps (Aquamaps.org) species distribution models for our study area for the following species:
Dict <- tibble::tribble(
~nameCommon, ~nameVariable, ~category,
"Green sea turtle", "Chelonia_mydas", "Reptiles",
"Loggerhead sea turtle", "Caretta_caretta", "Reptiles",
"Hawksbill sea turtle", "Eretmochelys_imbricata", "Reptiles",
"Olive ridley sea turtle", "Lepidochelys_olivacea", "Reptiles",
"Saltwater crocodile", "Crocodylus_porosus", "Reptiles",
"Humpback whale", "Megaptera_novaeangliae", "Mammals",
"Common Minke whale", "Balaenoptera_acutorostrata", "Mammals",
"Dugong", "Dugong_dugon", "Mammals",
"Grey nurse shark", "Carcharias_taurus", "Sharks and rays",
"Tiger shark", "Galeocerdo_cuvier", "Sharks and rays",
"Great hammerhead shark", "Sphyrna_mokarran", "Sharks and rays",
"Giant oceanic manta ray", "Mobula_birostris", "Sharks and rays",
"Reef manta ray", "Mobula_alfredi", "Sharks and rays",
"Whitetip reef shark", "Triaenodon_obesus", "Sharks and rays",
"Red-footed booby", "Sula_sula", "Birds"
)
These species were not chosen based on their importance for this region and only represent an example for visualization purposes.
Note: The structure of the tribble
above
is required for some of the downstream plotting. Common denotes
the common name of a species, nameVariable the scientific name
in the format used by Aquamaps, TaxGroup is the taxonomic
grouping that a species belongs to and Category represents the
importance of the species for the conservation plan.
Convert the probabilities to binary data
datEx_species_bin <- spDataFiltered %>%
splnr_apply_cutoffs(Cutoffs = 0.5)
We can now look at the feature data used for the spatial plan
individually by calling splnr_plot_binFeature()
, for
example to see the binary habitat suitability map for Green sea
turtles:
(ggFeature1 <- splnr_plot(
df = datEx_species_bin,
col_names = "Chelonia_mydas",
plot_title = "Chelonia mydas",
legend_labels = c("Absence", "Presence")
) +
splnr_gg_add(
PUs = PUs, Bndry = Bndry, overlay = landmass,
cropOverlay = PUs, ggtheme = splnr_theme
)
)
The suitable habitat for Green sea turtles as predicted by Aquamaps is restricted to few cells close to the coast. If we now compare this with the predicted suitable habitat for Humpback whales, we can see that they are fairly ubiquitous across the whole Coral Sea.
(ggFeature <- splnr_plot(
datEx_species_bin,
"Megaptera_novaeangliae",
plot_title = "Megaptera novaeangliae"
) +
splnr_gg_add(
PUs = PUs, Bndry = Bndry, overlay = landmass,
cropOverlay = PUs, ggtheme = splnr_theme
))
In our example, this was the only reason why we classified species as either representative if their suitable habitat is wide-ranging within the study region or important if they are restricted to a few number of cells.
To get a better idea of the overall distribution of the used features, we can also plot the number of features with suitable habitat within a planning unit of the study region.
(ggFeatNo <- splnr_plot(df = datEx_species_bin,
col_names = colnames(datEx_species_bin %>%
sf::st_drop_geometry() %>%
dplyr::select(-"cellID")),
plot_title = "",
legend_title = "Number of features") +
splnr_gg_add(
PUs = PUs, Bndry = Bndry, overlay = landmass,
cropOverlay = PUs, ggtheme = splnr_theme
))
Prepare Data for prioritisation
For the spatial prioritization we also need to extract the names of
our features to pass into prioritizr
.
feature_names <- splnr_featureNames(datEx_species_bin)
We also create an sf
object that contains all the
information needed for the prioritization.
out_sf <- datEx_species_bin
Add Cost
In our example, we use a minimum set objective function, which aims to minimize the cost whilst meeting all the conservation targets. We add an area-based cost to include as little area as possible in the spatial plan whilst meeting the conservation targets. For this, all the planning units are assigned an equal cost of 1.
out_sf$Cost_None <- 1
(ggCost <- splnr_plot(out_sf, col_names = "Cost_None",
legend_title = "Cost", legend_labels = "1") +
splnr_gg_add(
PUs = PUs, Bndry = Bndry, overlay = landmass,
cropOverlay = PUs, ggtheme = splnr_theme
))
Other features
Fishing effort
The gfwr package allows us to recover data from fisheries across the
world, we set here the parameter compress
as
TRUE
to recover the Apparent fishing hours
per
coordinates.
gfw_data <- splnr_get_gfw(region = 'Australia',
start_date = "2022-01-01",
end_date = "2022-12-31",
temp_res = "yearly",
cCRS = cCRS,
compress = TRUE) %>%
sf::st_interpolate_aw(PUs, extensive = TRUE)
out_sf$Apparent.Fishing.Hours <- 0 # Add column to PUs
out_sf$Apparent.Fishing.Hours[as.numeric(rownames(PUs))] <-
gfw_data$Apparent.Fishing.Hours # Put corresponding data in PUs
(ggCost <- splnr_plot(out_sf, col_names = "Apparent.Fishing.Hours") +
splnr_gg_add(
PUs = PUs, Bndry = Bndry, overlay = landmass,
cropOverlay = PUs, ggtheme = splnr_theme
))
Set Targets
As shown previously, we assigned the conservation features a class reflecting their importance in the planning region. Conservation targets are then assigned a target based on their class, in our case 30% of suitable habitat of important and 10% of representative features.
catTarg <- c("Reptiles" = 0.3, "Mammals" = 0.1, "Sharks and rays" = 0.1, "Birds" = 0.1)
target <- Dict %>%
splnr_targets_byCategory(catTarg, catName = "category")
Note: The assigned classes and targets were not based on any ecological information and only chosen for visualization purposes.
Set up conservation problem
datEx_problem <- prioritizr::problem(out_sf, feature_names, "Cost_None") %>%
prioritizr::add_min_set_objective() %>%
prioritizr::add_relative_targets(target$target) %>%
prioritizr::add_binary_decisions() %>%
prioritizr::add_default_solver(verbose = FALSE)
Solve the conservation problem
datEx_soln <- datEx_problem %>%
prioritizr::solve.ConservationProblem()
Visualize Output
There are different ways to visualize the output of the prioritization that can be loosely grouped into three categories: + Visualization of the solution + Visualization of targets + Visualization of importance scores
Visualization of the solution
(ggSoln <- splnr_plot(datEx_soln,
col_names = "solution_1",
legend_title = "Solution",
legend_labels = c("0","1")) +
splnr_gg_add(
PUs = PUs, Bndry = Bndry, overlay = landmass,
cropOverlay = PUs, ggtheme = splnr_theme
))
This plot shows the optimal solution for the planning region that meets the selected targets for the chosen features for the smallest area possible. The categorical map displays, which of the planning units were selected as important for meeting the conservation targets (dark blue) and which were not selected (light blue). This can also be done with an overlay of the cost to show how the solution avoids highly costly areas:
(ggCostOverlay <- splnr_plot_costOverlay(
soln = datEx_soln,
Cost = NA,
Cost_name = "Cost_None"
) +
splnr_gg_add(
PUs = PUs, Bndry = Bndry, overlay = landmass,
cropOverlay = PUs, ggtheme = splnr_theme
))
Note: In our example, cost is equal for all planning units.
Visualization of targets
To visualize how well the targets are met, we first need to extract how much suitable habitat of each feature are selected in the spatial plan. This also includes potential incidental coverage of feature that were not included in the spatial plan but can still be found in the planning region.
dfTarget <- splnr_get_featureRep(datEx_soln, datEx_problem,
climsmart = FALSE,
solnCol = "solution_1"
)
(ggTarget <- splnr_plot_featureRep(dfTarget,
category = Dict,
renameFeatures = TRUE,
namesToReplace = Dict,
categoryFeatureCol = "nameCommon",
nr = 1, showTarget = TRUE,
))
For a circular bar plot, one additional step of data preparation needs to be done.
# dfTargetCirc <- dfTarget %>%
# dplyr::select("feature", "value", "group") %>%
# na.omit()
# colors <- c(
# "important" = "darkgreen",
# "representative" = "darkred"
# )
# legends <- c("Important", "Representative")
# (ggCircTarg <- splnr_plot_circBplot(df = dfTargetCirc, legend_list = legends, legend_color = colors, impTarget = 30, repTarget = 10))
Visualization of importance scores
Importance scores can help to assess the relative importance of an individual selected planning unit in the spatial plan (for more information, see https://prioritizr.net/reference/importance.html)
Here, we use two different importance scores, the Ferrier Score and Rarity Weighted Richness.
ggFerrier <- splnr_plot_importanceScore(
soln = datEx_soln,
pDat = datEx_problem,
method = "Ferrier",
decimals = 4,
legendTitle = "Importance Score \n(Ferrier Score)"
) +
splnr_gg_add(
PUs = PUs, Bndry = Bndry, overlay = landmass,
cropOverlay = PUs, ggtheme = splnr_theme
)
#> Ferrier Score.
ggRWR <- splnr_plot_importanceScore(
soln = datEx_soln,
pDat = datEx_problem,
method = "RWR",
decimals = 2,
legendTitle = "Importance Score \n(Rarity Weighted Richness)"
) +
splnr_gg_add(
PUs = PUs, Bndry = Bndry, overlay = landmass,
cropOverlay = PUs, ggtheme = splnr_theme
)
#> Rarity Wighted Richness.
(ggScores <- patchwork::wrap_plots(ggFerrier + ggRWR))
In our example, both scores label similar -coastal- planning units as most important for the spatial plan.
Comparing Spatial Plans
Sometimes it can be useful to have a direct comparison of two spatial plans. To show how to achieve this with this package, we first need a second conservation problem and resulting solution.
Here, our second spatial plan will include already existing marine protected areas in the area (https://www.protectedplanet.net/en/thematic-areas/wdpa?tab=WDPA) with the following characteristics: * Status = c(“Designated”, “Established”, “Inscribed”) * Designation Type = c(“National”, “Regional”, “International”, “Not Applicable”) * IUCN Category = c(“Ia”, “Ib”, “II”, “III”, “IV”)
# The user can download their own MPAs using this code,
# but below we use data already within the package.
LockedIn <- splnr_get_MPAs(PUs, "Australia") %>%
splnr_apply_cutoffs(0.5) %>%
dplyr::mutate(wdpa = as.logical(wdpa))
(ggMPA <- splnr_plot(MPAsCoralSea, "wdpa") +
splnr_gg_add(
PUs = PUs, Bndry = Bndry, overlay = landmass,
cropOverlay = PUs, ggtheme = splnr_theme
))
We will also include targets based on IUCN categories to prioritise species with an IUCN status of:
- Vulnerable
- Endangered
- Critically Endangered
- Extinct in the Wild
- Extinct
We assign a 30% target to species within these categories. All species that do not fall into any of these categories receive an inverse area target, so species with a greater area of suitable habitat are assigned a lower target.
minTarget <- 0.1
maxTarget <- 0.2
# Create inverse area target
IA_Targets <- splnr_targets_byInverseArea(
datEx_species_bin,
minTarget,
maxTarget
)
We can also adjust the targets based on the IUCN Category. Here we apply an increased target of 0.3 for all species with an increased thread level on the IUCN Red List(“EX”, “EW”, “CR”, “EN”, “VU”).
IUCN_IA_Targets <- IA_Targets %>%
splnr_get_IUCNRedList(species_col = "Species") %>% # Add RL data to the df
splnr_targets_byIUCN(IUCN_target = 0.3)
Note: Accessing the IUCN database requires a login
token from rl_use_iucn()
that needs to be added to the
environment using
Sys.setenv(IUCN_REDLIST_KEY = "[Your Token]")
. You can
start by running rredlist::rl_use_iucn()
.
Set up second conservation problem
datEx_problem2 <- prioritizr::problem(out_sf, feature_names, "Cost_None") %>%
prioritizr::add_min_set_objective() %>%
prioritizr::add_relative_targets(IA_Targets$target) %>%
prioritizr::add_locked_in_constraints(as.logical(MPAsCoralSea$wdpa)) %>%
prioritizr::add_binary_decisions() %>%
prioritizr::add_default_solver(verbose = FALSE)
# Add a solution object
datEx_soln2 <- datEx_problem2 %>%
prioritizr::solve.ConservationProblem()
(ggSoln2 <- splnr_plot_solution(datEx_soln2) +
splnr_gg_add(
PUs = PUs, Bndry = Bndry, overlay = landmass,
cropOverlay = PUs, ggtheme = splnr_theme
))
But we locked in areas that were already existing MPAs. If we want to
show the overlap between the selected planning units and the current
MPAs, we can can add this to the
splnr_gg_add()
function.
(splnr_plot_solution(datEx_soln2) +
splnr_gg_add(
PUs = PUs, Bndry = Bndry, lockIn = MPAsCoralSea,
nameLockIn = "wdpa", typeLockIn = "Full",
colorLockIn = "lightgrey", alphaLockIn = 0.2, overlay = landmass,
cropOverlay = PUs, ggtheme = splnr_theme
))
If we instead only want to see the contours of the locked in areas we
can set typeLockIn = "Contours"
in
splnr_gg_add()
.
(splnr_plot_solution(datEx_soln2) +
splnr_gg_add(
lockIn = MPAsCoralSea,
nameLockIn = "wdpa", typeLockIn = "Contours",
colorLockIn = "lightgrey", alphaLockIn = 0.2, overlay = landmass,
cropOverlay = PUs, ggtheme = splnr_theme
))
Visualize comparison
(ggComp <- splnr_plot_comparison(datEx_soln, datEx_soln2) +
splnr_gg_add(
PUs = PUs, Bndry = Bndry, overlay = landmass,
cropOverlay = PUs, ggtheme = splnr_theme
))
This plot shows how the first solution (without current MPAs) differs from the second solution (including current MPAs. The categorical map displays, which of the planning units were selected in solution 2 but not in solution 1 (red), in solution 1 but not in solution 2 (blue), or selected in both solutions (grey).
CorrMat <- splnr_get_kappaCorrData(list(datEx_soln, datEx_soln2),
name_sol = c("soln1", "soln2")
)
(ggCorr <- splnr_plot_corrMat(CorrMat,
AxisLabels = c("Solution 1", "Solution 2")
))
The correlation matrix shows the similarity as the Cohen’s Kappa correlation between solution 1 and solution 2.
Plotting selection frequency
Sometimes when multiple spatial plans are generated, we are interesting in how many times a planning unit is selected across the array of solutions. To demonstrate how this can be done using this package, we first create an array (= portfolio) of solutions. One example of this is by using the portfolio
datEx_soln_portfolio <- datEx_problem %>%
prioritizr::add_cuts_portfolio(5) %>% # create a portfolio of solutions
prioritizr::solve.ConservationProblem()
selFreq <- datEx_soln_portfolio %>% # calculate selection frequency
sf::st_drop_geometry() %>%
dplyr::mutate(selFreq = as.factor(rowSums(
dplyr::select(., dplyr::starts_with("solution_"))
))) %>%
sf::st_as_sf(geometry = datEx_soln_portfolio$geometry) %>%
dplyr::select(selFreq)
(ggselFreq <- splnr_plot_selectionFreq(selFreq) +
splnr_gg_add(
PUs = PUs, Bndry = Bndry, overlay = landmass,
cropOverlay = PUs, ggtheme = splnr_theme
))