This report summarises models fitted to the 2024 captures dataset,
with a shared pi
vector for all species (per fishery
group), using updated (2025) density maps where available.
Load packages required for data preparation:
## Warning: package 'sf' was built under R version 4.4.2
## Linking to GEOS 3.12.2, GDAL 3.9.3, PROJ 9.4.1; sf_use_s2() is TRUE
## sefra-seabird version 2.4.0 (18-Mar-2025)
## sefraInputs version 0.0.1 (24-Mar-2025)
##
## Attaching package: 'sefraInputs'
## The following object is masked from 'package:sefra':
##
## versionUpdate
Source data from sefraInputs
:
Extract biological data from 2024 risk assessment:
## Loaded data:
##
##
## |name |description |created |version | id|
## |:---------|:--------------|:-------------------|:----------------------|--:|
## |inputsBio |2024_CCSBT_SRA |2025-03-24 20:25:44 |20250324T202544Z-514b3 | 1|
inputs_bio_option <- inputsBio
invisible(sapply(names(inputs_bio_option), function(i) {
assign(i, value = inputs_bio_option[[i]], envir = .GlobalEnv)
message("Created ", i)
}))
## Created sp_codes
## Created sp_groups
## Created breeding_season
## Created p_nest
## Created breeding_phenology
## Created p_southern
## Created N_BP
## Created P_B
## Created S_curr
## Created S_opt
## Created A_curr
## Created A_opt
Extract cryptic capture multipliers from 2024 risk assessment:
## Loaded data:
##
##
## |name |description |created |version | id|
## |:------------------------|:-----------|:-------------------|:----------------------|--:|
## |cryptic_capture_longline |reference |2025-03-24 20:25:44 |20250324T202544Z-240cc | 1|
Fisheries input data are stored in the sefraData
object
in three data frames:
Get function to load data files, and reference data hashes:
Read in prepped data objects:
data_path <- "../../data-local/model-inputs-2024/_prepped_inputs_e_updated_maps"
load(file.path(data_path, "codes_exclude.rda"))
overlap_o <- load_data_file(file = file.path(data_path, "overlap_o.rda"), lk_data_hash)
captures_o <- load_data_file(file = file.path(data_path, "captures_o.rda"), lk_data_hash)
It is necessary to reallocate species-specific captures of royal albatrosses and black-browed albatrosses to the complex-level capture codes, so that each species code has either one species-specific capture code or one complex-level capture code, but not both.
Add species-specific captures of royal albatrosses to complex code, and remove capture codes:
ndx <- captures_o$code %in% c("DIP", "DIQ")
captures_o$code[ndx] <- "DRA"
captures_o$id_code[ndx] <- 27
codes_exclude <- c(codes_exclude, c("DIP", "DIQ"))
Add species-specific captures of black-browed albatrosses to complex code, and remove capture codes:
ndx <- captures_o$code %in% c("DIM", "TQW")
captures_o$code[ndx] <- "DBB"
captures_o$id_code[ndx] <- 30
codes_exclude <- c(codes_exclude, c("DIM", "TQW"))
Exclude captures records where capture code is in
codes_exclude
:
Specify where to save outputs:
## directory contains: catchabilities_boxplot.png, fit_cumulative_captures_barchart_capture_code.png, fit_cumulative_captures_point_capture_code.png, fit_empirical_captures_barchart_capture_code.png, fit_empirical_captures_point_capture_code.png, log10_catchabilities.png, log10_catchabilities_boxplot.png, log10_catchability_coef_fishery_group.png, pi_boxplot.png, prior_updates_N_BP.png, prior_updates_P_B.png, trace_plot.png, deaths.png, deaths_caption.tex, density_overlap.png, density_overlap_caption.tex, mdl_ini.rda, out.rda, sefra_data.rda, catchability_coefficients_fishery_group.tex, fit_captures_per_code_fishery_group.tex, fit_captures_per_species_group_fishery_group.tex, q_per_species_group_fishery_group.tex, q_per_species_group_fishery_group_alternative.tex
sefraData
objectFirst, identify capture codes to be used in model:
Initialise the data object:
## capture codes input: including all contributing species
## constructed 'sefraData' object
## Species
## code common_name scientific_name
## 1 DIW Gibson's albatross Diomedea antipodensis gibsoni
## 2 DQS Antipodean albatross Diomedea antipodensis antipodensis
## 3 DIX Wandering albatross Diomedea exulans
## 4 DBN Tristan albatross Diomedea dabbenena
## 5 DAM Amsterdam albatross Diomedea amsterdamensis
## 6 DIP Southern royal albatross Diomedea epomophora
## 7 DIQ Northern royal albatross Diomedea sanfordi
## 8 DCR Atlantic yellow-nosed albatross Thalassarche chlororhynchos
## 9 TQH Indian yellow-nosed albatross Thalassarche carteri
## 10 DIM Black-browed albatross Thalassarche melanophris
## 11 TQW Campbell black-browed albatross Thalassarche impavida
## 12 DCU Shy albatross Thalassarche cauta
## 13 TWD New Zealand white-capped albatross Thalassarche cauta steadi
## 14 DKS Salvin's albatross Thalassarche salvini
## 15 DER Chatham Island albatross Thalassarche eremita
## 16 DIC Grey-headed albatross Thalassarche chrysostoma
## 17 DSB Southern Buller's albatross Thalassarche bulleri bulleri
## 18 DNB Northern Buller's albatross Thalassarche bulleri platei
## 19 PHU Sooty albatross Phoebetria fusca
## 20 PHE Light-mantled sooty albatross Phoebetria palpebrata
## 21 PCI Grey petrel Procellaria cinerea
## 22 PRK Black petrel Procellaria parkinsoni
## 23 PCW Westland petrel Procellaria westlandica
## 24 PRO White-chinned petrel Procellaria aequinoctialis
## 25 PCN Spectacled petrel Procellaria conspicillata
## genus family code_resolution id_species
## 1 Diomedea Diomedeidae species 1
## 2 Diomedea Diomedeidae species 2
## 3 Diomedea Diomedeidae species 3
## 4 Diomedea Diomedeidae species 4
## 5 Diomedea Diomedeidae species 5
## 6 Diomedea Diomedeidae species 6
## 7 Diomedea Diomedeidae species 7
## 8 Thalassarche Diomedeidae species 8
## 9 Thalassarche Diomedeidae species 9
## 10 Thalassarche Diomedeidae species 10
## 11 Thalassarche Diomedeidae species 11
## 12 Thalassarche Diomedeidae species 12
## 13 Thalassarche Diomedeidae species 13
## 14 Thalassarche Diomedeidae species 14
## 15 Thalassarche Diomedeidae species 15
## 16 Thalassarche Diomedeidae species 16
## 17 Thalassarche Diomedeidae species 17
## 18 Thalassarche Diomedeidae species 18
## 19 Phoebetria Diomedeidae species 19
## 20 Phoebetria Diomedeidae species 20
## 21 Procellaria Procellariidae species 21
## 22 Procellaria Procellariidae species 22
## 23 Procellaria Procellariidae species 23
## 24 Procellaria Procellariidae species 24
## 25 Procellaria Procellariidae species 25
Assign biological inputs to the data object. Assignment functions are provided for each data type, and automatically select the required species:
n_breeding_pairs(sefra_data) <- N_BP
adult_survival(sefra_data) <- S_opt
p_breeding(sefra_data) <- P_B
age_breeding(sefra_data) <- A_curr
p_nest(sefra_data) <- p_nest
p_southern(sefra_data) <- p_southern
We can view the input data using, for example:
## id_species code distribution par1 par2
## 1 1 DIW log-normal 5400.00 0.050
## 2 2 DQS log-normal 3255.00 0.050
## 3 3 DIX log-normal 10072.00 0.050
## 4 4 DBN weibull 9.25 1710.000
## 5 5 DAM log-normal 60.00 0.100
## 6 6 DIP log-normal 6347.00 0.140
## 7 7 DIQ log-normal 4261.00 0.110
## 8 8 DCR log-normal 26800.00 0.100
## 9 9 TQH log-normal 33988.00 0.100
## 10 10 DIM log-normal 681000.00 0.050
## 11 11 TQW log-normal 24338.00 0.050
## 12 12 DCU log-normal 15335.00 0.100
## 13 13 TWD log-normal 71400.00 0.110
## 14 14 DKS log-normal 58563.00 0.100
## 15 15 DER log-normal 5294.00 0.010
## 16 16 DIC log-normal 80633.00 0.050
## 17 17 DSB log-normal 14320.00 0.050
## 18 18 DNB log-normal 19354.00 0.050
## 19 19 PHU weibull 23.20 13660.000
## 20 20 PHE log-normal 20927.00 0.100
## 21 21 PCI log-normal 105617.00 0.150
## 22 22 PRK log-normal 5456.00 0.057
## 23 23 PCW log-normal 6223.00 0.061
## 24 24 PRO log-normal 1317300.00 0.100
## 25 25 PCN log-normal 42000.00 0.096
## distribution par1 par2
## DIW log-normal 5400.00 0.050
## DQS log-normal 3255.00 0.050
## DIX log-normal 10072.00 0.050
## DBN weibull 9.25 1710.000
## DAM log-normal 60.00 0.100
## DIP log-normal 6347.00 0.140
## DIQ log-normal 4261.00 0.110
## DCR log-normal 26800.00 0.100
## TQH log-normal 33988.00 0.100
## DIM log-normal 681000.00 0.050
## TQW log-normal 24338.00 0.050
## DCU log-normal 15335.00 0.100
## TWD log-normal 71400.00 0.110
## DKS log-normal 58563.00 0.100
## DER log-normal 5294.00 0.010
## DIC log-normal 80633.00 0.050
## DSB log-normal 14320.00 0.050
## DNB log-normal 19354.00 0.050
## PHU weibull 23.20 13660.000
## PHE log-normal 20927.00 0.100
## PCI log-normal 105617.00 0.150
## PRK log-normal 5456.00 0.057
## PCW log-normal 6223.00 0.061
## PRO log-normal 1317300.00 0.100
## PCN log-normal 42000.00 0.096
Assign fishery groups:
## 4 fishery groups
## fishery_group id_fishery_group
## 1 NZL (DOM) 1
## 2 NZL (JV) 2
## 3 JPN 3
## 4 TWN 4
View capture codes:
## 21 capture codes:
## (empty captures data frame)
## code id_code resolution id_resolution
## 1 DKS 14 species 1
## 2 DER 15 species 1
## 3 DIC 16 species 1
## 4 PHU 19 species 1
## 5 PHE 20 species 1
## 6 PCI 21 species 1
## 7 PCN 25 species 1
## 8 DRA 27 complex 2
## 9 DYN 28 complex 2
## 10 DST 29 complex 2
## 11 DBB 30 complex 2
## 12 DIB 31 complex 2
## 13 DWC 32 complex 2
## 14 PRZ 33 complex 2
## 15 DIZ 34 genus 3
## 16 THZ 35 genus 3
## 17 PHZ 36 genus 3
## 18 PTZ 37 genus 3
## 19 ALZ 38 family 4
## 20 PRX 39 family 4
## 21 BLZ 40 class 5
Assign species groups:
## 5 species groups
## species_group id_species_group
## 1 Wandering albatross 1
## 2 Royal albatross 2
## 3 Mollymawk 3
## 4 Sooty albatross 4
## 5 Medium petrel 5
## 5 species groups
## (with 25 species)
## species species_group id_species id_species_group
## 1 DIW Wandering albatross 1 1
## 2 DQS Wandering albatross 2 1
## 3 DIX Wandering albatross 3 1
## 4 DBN Wandering albatross 4 1
## 5 DAM Wandering albatross 5 1
## 6 DIP Royal albatross 6 2
## 7 DIQ Royal albatross 7 2
## 8 DCR Mollymawk 8 3
## 9 TQH Mollymawk 9 3
## 10 DIM Mollymawk 10 3
## 11 TQW Mollymawk 11 3
## 12 DCU Mollymawk 12 3
## 13 TWD Mollymawk 13 3
## 14 DKS Mollymawk 14 3
## 15 DER Mollymawk 15 3
## 16 DIC Mollymawk 16 3
## 17 DSB Mollymawk 17 3
## 18 DNB Mollymawk 18 3
## 19 PHU Sooty albatross 19 4
## 20 PHE Sooty albatross 20 4
## 21 PCI Medium petrel 21 5
## 22 PRK Medium petrel 22 5
## 23 PCW Medium petrel 23 5
## 24 PRO Medium petrel 24 5
## 25 PCN Medium petrel 25 5
Assign cryptic capture distributions:
## 4 fishery groups
## 5 species groups
## distribution fishery_group species_group par value
## 1 log-normal NZL (DOM) Wandering albatross par1 1.420
## 2 log-normal NZL (JV) Wandering albatross par1 1.420
## 3 log-normal JPN Wandering albatross par1 1.420
## 4 log-normal TWN Wandering albatross par1 1.420
## 5 log-normal NZL (DOM) Royal albatross par1 1.420
## 6 log-normal NZL (JV) Royal albatross par1 1.420
## 7 log-normal JPN Royal albatross par1 1.420
## 8 log-normal TWN Royal albatross par1 1.420
## 9 log-normal NZL (DOM) Mollymawk par1 1.420
## 10 log-normal NZL (JV) Mollymawk par1 1.420
## 11 log-normal JPN Mollymawk par1 1.420
## 12 log-normal TWN Mollymawk par1 1.420
## 13 log-normal NZL (DOM) Sooty albatross par1 1.420
## 14 log-normal NZL (JV) Sooty albatross par1 1.420
## 15 log-normal JPN Sooty albatross par1 1.420
## 16 log-normal TWN Sooty albatross par1 1.420
## 17 log-normal NZL (DOM) Medium petrel par1 1.420
## 18 log-normal NZL (JV) Medium petrel par1 1.420
## 19 log-normal JPN Medium petrel par1 1.420
## 20 log-normal TWN Medium petrel par1 1.420
## 21 log-normal NZL (DOM) Wandering albatross par2 0.186
## 22 log-normal NZL (JV) Wandering albatross par2 0.186
## 23 log-normal JPN Wandering albatross par2 0.186
## 24 log-normal TWN Wandering albatross par2 0.186
## 25 log-normal NZL (DOM) Royal albatross par2 0.186
## 26 log-normal NZL (JV) Royal albatross par2 0.186
## 27 log-normal JPN Royal albatross par2 0.186
## 28 log-normal TWN Royal albatross par2 0.186
## 29 log-normal NZL (DOM) Mollymawk par2 0.186
## 30 log-normal NZL (JV) Mollymawk par2 0.186
## 31 log-normal JPN Mollymawk par2 0.186
## 32 log-normal TWN Mollymawk par2 0.186
## 33 log-normal NZL (DOM) Sooty albatross par2 0.186
## 34 log-normal NZL (JV) Sooty albatross par2 0.186
## 35 log-normal JPN Sooty albatross par2 0.186
## 36 log-normal TWN Sooty albatross par2 0.186
## 37 log-normal NZL (DOM) Medium petrel par2 0.186
## 38 log-normal NZL (JV) Medium petrel par2 0.186
## 39 log-normal JPN Medium petrel par2 0.186
## 40 log-normal TWN Medium petrel par2 0.186
Observed capture and overlap data for estimation of catchabilities:
## Prepared observer captures and overlap data
Overlap data for full diagnostics outputs:
## Prepared commercial (total) overlap data
Force taxonomic resolution of species and complex capture codes to be
equivalent (i.e., so they share the same pi
term):
sefra_data$n_resolutions <- 4
sefra_data$id_resolutions <- sefra_data$id_resolutions[!sefra_data$id_resolutions %in% 2L]
sefra_data$resolutions[sefra_data$resolutions %in% c("species", "complex")] <- "species"
sefra_data$code_resolution[sefra_data$code_resolution %in% 2L] <- 1L
Force all species to share the same pi vector:
Specify number of iterations:
First, source and compile the model code. Because there are no commercial data included, this model will not generate a full suite of diagnostic outputs (only catchability and catches):
## SEFRA-seabird model v2.4.0
Create initial values:
Run model and check MCMC trace plots:
Make folders and subfolders for outputs:
make_folder(file.path(output_path, "maps"), clean = TRUE)
make_folder(file.path(output_path, "figures"), clean = TRUE)
make_folder(file.path(output_path, "tables"), clean = TRUE)
Create and save sefraOutputs
object that holds
summarised model outputs:
## constructed 'sefraOutputs' object
## Info useful for writing script
x <- rstan::extract(mdl_fit, pars = "lp__", permute = FALSE, include = FALSE)
x <- dimnames(x)[[3]]
x <- gsub("\\[.*$", "", x)
x <- unique(x)
quantity_names <- x
Discrete colour palette that is colour-blind friendly:
## Colour blind friendly palette by Okabe & Ito
okabe_cols <- c("#56B4E9", "#E69F00", "#009E73", "#F0E442", "#CC79A7", "#0072B2", "#D55E00", "#000000")
names(okabe_cols) <- c("light blue", "orange", "green", "yellow", "pink", "dark blue", "red", "black")
## function to get summary statistics (mean and 95% CI)
summary_fn <- function(x, var) {
summarise(x, mean = mean({{ var }}), mq = median({{ var }}),
lq = as.numeric(quantile({{ var }}, 0.025)), uq = as.numeric(quantile({{ var }}, 0.975)))
}
## summary function that gets quantiles to generate boxplot of relative mortalities
summary_fn_boxplot <- function(x, var) {
summarise(x, lq = as.numeric(quantile({{ var }}, probs = 0.025)), lmq = as.numeric(quantile({{ var }}, probs = 0.125)),
mq = as.numeric(quantile({{ var }}, probs = 0.5)),
umq = as.numeric(quantile({{ var }}, probs = 0.875)), uq = as.numeric(quantile({{ var }}, probs = 0.975)))
}
Set colours for each species group:
cols_species_group <- okabe_cols[1:length(sefra_data[['species_groups']])]
names(cols_species_group) <- sefra_data[['species_groups']]
Specify order of groups for plots:
sp_group_levels <- species_groups(sefra_data) %>% filter(., !is.na(species_group)) %>% select(., id_species_group, species_group) %>% distinct(.) %>% with(., species_group)
## 5 species groups
Specify colours for taxonomic resolutions (e.g., used in plots of
pi
parameters):
taxo_resolution <- sp_groups %>% select(., taxonomic_resolution) %>% distinct(.) %>% with(., taxonomic_resolution)
taxo_resolution[taxo_resolution %in% "bird"] <- "class"
cols_taxo_resolution <- okabe_cols[1:length(taxo_resolution)]
names(cols_taxo_resolution) <- taxo_resolution
Create variable for plots with taxonomic grouping (genus, family or class):
sp_groups <- sp_groups %>%
mutate(taxo_group = case_when(
taxonomic_resolution %in% c("species", "complex", "genus") ~ genus,
taxonomic_resolution %in% "family" ~ family,
.default = "Unspecified"
))
taxo_group_levels <- sp_groups %>% select(., taxo_group) %>% distinct(.) %>% with(., taxo_group)
cols_taxo_group <- okabe_cols[1:length(taxo_group_levels)]
names(cols_taxo_group) <- taxo_group_levels
Trace plots can be used to visualise convergence. For example, we can plot trace diagnostics for the biological parameters using:
trace_plot(mdl_fit, pars = c("n_breeding_pairs"), labels = paste0('N[', sefra_data$species, ']')) + facet_wrap(~parameter, scales = "free_y")
Trace plots of catchability parameters:
#trace_plot(mdl_fit, pars = c("alpha_intercept"))
#trace_plot(mdl_fit, pars = c("alpha_fishery_group"))
#trace_plot(mdl_fit, pars = c("alpha_species_group"))
trace_plot(mdl_fit, pars = c("q")) + facet_wrap(~parameter, scales = "free_y") + theme(axis.text.y = element_blank())
Trace plots of probability of live capture:
#trace_plot(mdl_fit, pars = c("beta_intercept"))
#trace_plot(mdl_fit, pars = c("beta_fishery_group"))
#trace_plot(mdl_fit, pars = c("beta_species_group"))
trace_plot(mdl_fit, pars = c("p_live")) + facet_wrap(~parameter, scales = "free_y") + theme(axis.text.y = element_blank())
Trace plots of probability of observed capture:
par_name <- "p_obs_logit"
#if("p_obs_cde" %in% quantity_names) par_name <- "p_obs_cde"
trace_plot(mdl_fit, pars = par_name) + facet_wrap(~parameter, scales = "free_y") + theme(axis.text.y = element_blank())
To visualise prior updates to the biological input distributions, we use, for example:
ggsave(gg, file = file.path(output_path, "figures", "prior_updates_N_BP.png"), width = 8, height = 12)
ggsave(gg, file = file.path(output_path, "figures", "prior_updates_N_BP.pdf"), width = 8, height = 12)
gg <- plot_prior_update(mdl_fit, par = "n_breeding_pairs", labels = sefra_data$species) + scale_y_log10()
gg
ggsave(gg, file = file.path(output_path, "figures", "prior_updates_N_BP_log10.png"), width = 8, height = 12)
ggsave(gg, file = file.path(output_path, "figures", "prior_updates_N_BP_log10.pdf"), width = 8, height = 12)
gg <- plot_prior_update(mdl_fit, par = "p_breeding", labels = sefra_data$species)
gg
Diagnostic plots also exist for Rhat and Neff. For example:
plot_rhat(mdl_fit, pars = c("alpha_fishery_group", "alpha_species_group", "beta_fishery_group", "beta_species_group"))
Trace plot of summary statistics:
x <- rstan::extract(mdl_fit, pars = paste0("traces[", 1:4, "]"), permute = FALSE)
dimnames(x) <- list(iteration = 0.5 * n_iter + (1:dim(x)[1]), chain = paste0("chain_", 1:dim(x)[2]),
parameter = c("Catchability", "Prob. live", "Vuln. breeders", "lambda"))
x <- reshape2::melt(x)
gg <- ggplot(x) +
geom_line(aes(iteration, value, col = chain)) +
scale_color_viridis_d(option = "D", begin = 0.2, end = 0.8) +
facet_wrap(vars(parameter), ncol = 1, scales = "free_y") +
theme_bw(base_size = 14) +
theme(axis.text.y = element_blank(), axis.title.y = element_blank()) +
guides(col = "none") + xlab("Posterior sample")
gg
Perhaps the most useful diagnostic is provided from examination of fits to the capture data, and a specific function exists for this purpose:
## $captures
## # A tibble: 84 × 7
## fishery_group code captures hat med low_ci upp_ci
## <fct> <chr> <int> <dbl> <dbl> <dbl> <dbl>
## 1 NZL (DOM) DKS 1 17.5 17 9 27.0
## 2 NZL (DOM) DER 0 0.883 1 0 3
## 3 NZL (DOM) DIC 1 0.436 0 0 2
## 4 NZL (DOM) PHU 0 0 0 0 0
## 5 NZL (DOM) PHE 0 0.816 0 0 4
## 6 NZL (DOM) PCI 4 33.0 32 20 49
## 7 NZL (DOM) PCN 0 0 0 0 0
## 8 NZL (DOM) DRA 11 11.0 11 3 22
## 9 NZL (DOM) DYN 0 0 0 0 0
## 10 NZL (DOM) DST 151 102. 102 78.0 127
## # ℹ 74 more rows
##
## $captures_inclusive
## # A tibble: 84 × 7
## fishery_group code captures hat med low_ci upp_ci
## <chr> <chr> <int> <dbl> <dbl> <dbl> <dbl>
## 1 JPN DKS 0 20.9 21 11 31
## 2 JPN DER 3 4.55 4 1 9
## 3 JPN DIC 840 773. 772. 699 851
## 4 JPN PHU 134 141. 140 111 172
## 5 JPN PHE 95 75.2 75 54 99.0
## 6 JPN PCI 152 101. 101 77 127
## 7 JPN PCN 44 28.1 28 17 41
## 8 JPN DRA 21 21.4 21 10 35.0
## 9 JPN DYN 205 303. 301 260. 353
## 10 JPN DST 796 808. 807 735. 880.
## # ℹ 74 more rows
‘Cumulative’ captures for a given capture code include all captures from other capture codes recorded at finer taxonomic resolutions. For example, cumulative captures for ‘PTZ’ (Procellaria genus) includes captures identified as an unspecified Procellaria species, as well as all captures identified at a species or complex level within the Procellaria genus (e.g., black petrels).
‘Empirical’ captures for a given capture code only include captures identified as that specific capture code. For example, empirical captures for ‘PTZ’ (Procellaria genus) only includes captures with an assigned capture code of ‘PTZ’ - i.e., identified as an unspecified Procellaria species.
The model can be fitted to either cumulative or empirical captures
(specified by the likelihood
argument to the
sefra
function). Comparisons of captures can be informative
for both cumulative and empirical captures, regardless of which type of
captures the model was fitted to. However, model fits should only be
assessed using the type of capture that the model was fitted to.
Comparisons of total empirical and cumulative captures (per capture code ), and total estimated captures (per species):
est_catch_spp <- posterior(mdl_fit, pars = c('E_MDL_captures'))
est_catch_code_emp <- posterior(mdl_fit, pars = c('E_EMP_captures'))
est_catch_code_csm <- posterior(mdl_fit, pars = c('E_CSM_captures'))
est_pi <- posterior(mdl_fit, pars = c('p_obs'))
## these should be equal:
sum(est_catch_spp)
## [1] 7541367
## [1] 7541367
## [1] 7541367
Get data-frame with observed and predicted cumulative captures by code:
x <- captures(sefra_data, mdl_fit)[["captures_inclusive"]]
y <- select(filter(sp_groups, !(code %in% codes_exclude)), code, common_name, species_group, taxo_group)
x <- x %>% left_join(y)
## Joining with `by = join_by(code)`
x <- x %>% mutate(
species_group = factor(species_group, levels = sp_group_levels),
taxo_group = factor(taxo_group, levels = taxo_group_levels),
fishery_group = factor(fishery_group, levels = fg_group_levels)
)
x <- x %>% mutate(., across(c(captures, hat, med, low_ci, upp_ci), function(a) a / sefra_data[["n_year_k"]]))
plt_dat_point <- x
plt_dat_bar <- x %>% tidyr::pivot_longer(captures:hat) %>% mutate(low_ci = case_when(name == "captures" ~ NA, TRUE ~ low_ci), upp_ci = case_when(name == "captures" ~ NA, TRUE ~ upp_ci), med = case_when(name == "captures" ~ NA, TRUE ~ med))
Barchart of observed vs predicted cumulative captures by capture code and fishery group:
## Get colour palette
plt_cols <- scales::viridis_pal(alpha = 0.7, option = "D", begin = 0.1, end = 0.9)(2)
names(plt_cols) <- c("captures", "hat")
## reorder capture codes for plot using ordering in sp_groups
plt_dat_bar <- plt_dat_bar %>% mutate(., code = factor(code, levels = sp_groups$code))
gg <- plt_dat_bar %>% ggplot(.) +
geom_col(aes(x = code, y = value, col = name, fill = name), position = "dodge") +
#geom_errorbar(aes(x = code, ymin = low_ci, ymax = upp_ci, col = name), position = "dodge", alpha = 1) +
scale_fill_manual("", values = plt_cols, aesthetics = c("fill", "color"), labels = c("Observed", "Posterior prediction")) +
xlab("Capture code") + ylab("Average annual captures") +
facet_wrap(vars(fishery_group), ncol = 1, scales = "free_y") +
theme_bw() + theme(legend.position = "bottom")
gg
ggsave(gg, file = file.path(output_path, "figures", "fit_cumulative_captures_barchart_capture_code.png"), width = 8)
## Saving 8 x 7 in image
ggsave(gg, file = file.path(output_path, "figures", "fit_cumulative_captures_barchart_capture_code.pdf"), width = 8)
## Saving 8 x 7 in image
Plots of observed vs. predicted cumulative captures by species group and fishery group:
gg <- plt_dat_point %>%
#filter(., obs > 0 & mq > 0) %>%
ggplot() +
geom_pointrange(aes(x = captures, y = med, ymin = low_ci, ymax = upp_ci, colour = taxo_group), alpha = 0.5, size = 1.0) +
scale_colour_manual("", values = cols_taxo_group) +
geom_abline(slope = 1) +
facet_wrap(fishery_group ~ .) +
theme_bw(base_size = 18) +
theme(legend.position = "bottom", legend.title = element_text(size = 14), legend.text = element_text(size = 12)) +
labs(x = "Observed number of annual captures", y = "Predicted number of annual observed captures") +
theme(aspect.ratio = 1) + scale_y_log10() + scale_x_log10()
gg
## Warning in scale_y_log10(): log-10 transformation introduced infinite values.
## log-10 transformation introduced infinite values.
## log-10 transformation introduced infinite values.
## Warning in scale_x_log10(): log-10 transformation introduced infinite values.
ggsave(gg, file = file.path(output_path, "figures", "fit_cumulative_captures_point_capture_code.png"), width = 10)
## Saving 10 x 10 in image
## Warning in scale_y_log10(): log-10 transformation introduced infinite values.
## Warning in scale_y_log10(): log-10 transformation introduced infinite values.
## log-10 transformation introduced infinite values.
## Warning in scale_x_log10(): log-10 transformation introduced infinite values.
ggsave(gg, file = file.path(output_path, "figures", "fit_cumulative_captures_point_capture_code.pdf"), width = 10)
## Saving 10 x 10 in image
## Warning in scale_y_log10(): log-10 transformation introduced infinite values.
## Warning in scale_y_log10(): log-10 transformation introduced infinite values.
## log-10 transformation introduced infinite values.
## Warning in scale_x_log10(): log-10 transformation introduced infinite values.
Get data-frame with observed and predicted empirical captures by code:
x <- captures(sefra_data, mdl_fit)[["captures"]]
y <- select(filter(sp_groups, !(code %in% codes_exclude)), code, common_name, species_group, taxo_group)
x <- x %>% left_join(y)
## Joining with `by = join_by(code)`
x <- x %>% mutate(
species_group = factor(species_group, levels = sp_group_levels),
taxo_group = factor(taxo_group, levels = taxo_group_levels),
fishery_group = factor(fishery_group, levels = fg_group_levels)
)
x <- x %>% mutate(., across(c(captures, hat, med, low_ci, upp_ci), function(a) a / sefra_data[["n_year_k"]]))
plt_dat_point <- x
plt_dat_bar <- x %>% tidyr::pivot_longer(captures:hat) %>% mutate(low_ci = case_when(name == "captures" ~ NA, TRUE ~ low_ci), upp_ci = case_when(name == "captures" ~ NA, TRUE ~ upp_ci), med = case_when(name == "captures" ~ NA, TRUE ~ med))
Barchart of observed vs predicted empirical captures by capture code and fishery group:
## Get colour palette
plt_cols <- scales::viridis_pal(alpha = 0.7, option = "D", begin = 0.1, end = 0.9)(2)
names(plt_cols) <- c("captures", "hat")
## reorder capture codes for plot using ordering in sp_groups
plt_dat_bar <- plt_dat_bar %>% mutate(., code = factor(code, levels = sp_groups$code))
gg <- plt_dat_bar %>% ggplot(.) +
geom_col(aes(x = code, y = value, col = name, fill = name), position = "dodge") +
#geom_errorbar(aes(x = code, ymin = low_ci, ymax = upp_ci, col = name), position = "dodge", alpha = 1) +
scale_fill_manual("", values = plt_cols, aesthetics = c("fill", "color"), labels = c("Observed", "Posterior prediction")) +
xlab("Capture code") + ylab("Average annual captures") +
facet_wrap(vars(fishery_group), ncol = 1, scales = "free_y") +
theme_bw() + theme(legend.position = "bottom")
gg
ggsave(gg, file = file.path(output_path, "figures", "fit_empirical_captures_barchart_capture_code.png"), width = 8)
## Saving 8 x 7 in image
ggsave(gg, file = file.path(output_path, "figures", "fit_empirical_captures_barchart_capture_code.pdf"), width = 8)
## Saving 8 x 7 in image
Plots of observed vs. predicted empirical captures by species group and fishery group:
gg <- plt_dat_point %>%
#filter(., obs > 0 & mq > 0) %>%
ggplot() +
geom_pointrange(aes(x = captures, y = med, ymin = low_ci, ymax = upp_ci, colour = taxo_group), alpha = 0.5, size = 1.0) +
scale_colour_manual("", values = cols_taxo_group) +
geom_abline(slope = 1) +
facet_wrap(fishery_group ~ .) +
theme_bw(base_size = 18) +
theme(legend.position = "bottom", legend.title = element_text(size = 14), legend.text = element_text(size = 12)) +
labs(x = "Observed number of annual captures", y = "Predicted number of annual observed captures") +
theme(aspect.ratio = 1) + scale_y_log10() + scale_x_log10()
gg
## Warning in scale_y_log10(): log-10 transformation introduced infinite values.
## log-10 transformation introduced infinite values.
## log-10 transformation introduced infinite values.
## Warning in scale_x_log10(): log-10 transformation introduced infinite values.
ggsave(gg, file = file.path(output_path, "figures", "fit_empirical_captures_point_capture_code.png"), width = 10)
## Saving 10 x 10 in image
## Warning in scale_y_log10(): log-10 transformation introduced infinite values.
## Warning in scale_y_log10(): log-10 transformation introduced infinite values.
## log-10 transformation introduced infinite values.
## Warning in scale_x_log10(): log-10 transformation introduced infinite values.
ggsave(gg, file = file.path(output_path, "figures", "fit_empirical_captures_point_capture_code.pdf"), width = 10)
## Saving 10 x 10 in image
## Warning in scale_y_log10(): log-10 transformation introduced infinite values.
## Warning in scale_y_log10(): log-10 transformation introduced infinite values.
## log-10 transformation introduced infinite values.
## Warning in scale_x_log10(): log-10 transformation introduced infinite values.
Estimated captures by species group:
x <- out[["captures_inclusive"]]
## Add id_code and species group information
x <- x %>% mutate(., id_code = as.numeric(code))
x <- x %>% mutate(., id_species_group = sefra_data[["species_to_species_group"]][id_code])
x <- x %>% left_join(., species_groups(sefra_data))
## 5 species groups
## Joining with `by = join_by(id_species_group)`
## Prepare observed captures
x <- x %>% #filter(., code %in% sefra_data$species) %>%
filter(., name %in% c("emp", "sim")) %>%
group_by(., fishery_group, species_group, name, iter) %>%
summarise(., value = sum(value)) %>% ungroup()
## `summarise()` has grouped output by 'fishery_group', 'species_group', 'name'.
## You can override using the `.groups` argument.
x <- x %>% group_by(., fishery_group, species_group, name) %>%
summarise(., mean = mean(value), mq = median(value),
lq = as.numeric(quantile(value, probs = 0.025)),
uq = as.numeric(quantile(value, probs = 0.975))) %>% ungroup()
## `summarise()` has grouped output by 'fishery_group', 'species_group'. You can
## override using the `.groups` argument.
## reorder species groups for plot
x$species_group <- factor(x$species_group, levels = sefra_data[['species_groups']])
## Restructure to have observed captures as a variable
tab_dat <- x %>%
filter(., name %in% "emp") %>%
select(., fishery_group, species_group, obs = mean)
tab_dat <- x %>% filter(., !name %in% "emp") %>%
left_join(tab_dat, ., by = c("fishery_group", "species_group"))
## Combine estimate and 95% CI
tab_dat <- tab_dat %>% mutate(., est = paste0(round(mean, 1), " (", round(lq, 1), "-", round(uq, 1), ")"))
tab_dat <- tab_dat %>% tidyr::pivot_wider(id_cols = species_group, values_from = c('obs', 'est'), names_from = fishery_group) %>%
arrange(., species_group)
## Reorder variables
tab_dat <- tab_dat %>% select('species_group', contains('DOM'), contains('JV'), contains('JPN'), contains('TWN'))
tab <- kable(tab_dat, format = 'latex',
col.names = c('', rep(c('Observed', 'Estimated'), times = sefra_data$n_fishery_groups)),
row.names = FALSE,
caption = "Fit to (cumulative) captures by species and fisheries group.",
label = 'fit_captures_by_species_group_fishery_group',
align = c('l', rep('r', times = ncol(tab_dat) - 1)),
linesep = "", booktabs = TRUE) %>%
add_header_above(c("Species group", "NZL (DOM)" = 2, "NZL (JV)" = 2, "JPN" = 2, "TWN" = 2), align = c('l', 'c', 'c', 'c', 'c')) %>%
kable_styling(font_size = 10, latex_options = "hold_position") %>%
sub("\\\\cmidrule\\(l\\{3pt\\}r\\{3pt\\}\\)\\{1-1\\}", "", .) %>%
sub("\\\\toprule", "", .) %>%
sub("\\\\bottomrule", "", .)
save_kable(tab, file = file.path(output_path, "tables", "fit_captures_per_species_group_fishery_group.tex"))
write.csv(tab_dat, file = file.path(output_path, "tables", "fit_captures_per_species_group_fishery_group.csv"))
Observed | Estimated | Observed | Estimated | Observed | Estimated | Observed | Estimated | |
---|---|---|---|---|---|---|---|---|
Wandering albatross | 2 | 20 (11-30) | 0 | 2.4 (0-6) | 1072 | 1014.8 (935-1102) | 92 | 155.8 (124-190) |
Royal albatross | 4 | 32.6 (19-48) | 0 | 0.8 (0-3) | 196 | 129.1 (103-158) | 56 | 50 (34-68) |
Mollymawk | 826 | 754.7 (660-843) | 152 | 136.6 (99-178) | 8269 | 8385.1 (8098-8677) | 1277 | 1204.8 (1099.9-1321) |
Sooty albatross | 417 | 411.6 (357-470) | 76 | 74.5 (52-101) | 5904 | 5902.5 (5691-6124.1) | 909 | 905.3 (827-992) |
Medium petrel | 417 | 416.4 (362-470) | 76 | 79.2 (56-104) | 6127 | 6127.9 (5916-6340.1) | 917 | 917.2 (837-1004) |
Estimated captures by code:
x <- out[["captures_inclusive"]]
## Add id_code and species group information
x <- x %>% mutate(., id_code = as.numeric(code))
x <- x %>% mutate(., id_species_group = sefra_data[["species_to_species_group"]][id_code])
x <- x %>% left_join(., species_groups(sefra_data))
## 5 species groups
## Joining with `by = join_by(id_species_group)`
## Prepare observed captures
x <- x %>% #filter(., code %in% sefra_data$species) %>%
filter(., name %in% c("emp", "sim")) %>%
group_by(., fishery_group, species_group, code, name, iter) %>%
summarise(., value = sum(value)) %>% ungroup()
## `summarise()` has grouped output by 'fishery_group', 'species_group', 'code',
## 'name'. You can override using the `.groups` argument.
x <- x %>% group_by(., fishery_group, species_group, code, name) %>%
summarise(., mean = mean(value), mq = median(value),
lq = as.numeric(quantile(value, probs = 0.025)),
uq = as.numeric(quantile(value, probs = 0.975))) %>% ungroup()
## `summarise()` has grouped output by 'fishery_group', 'species_group', 'code'.
## You can override using the `.groups` argument.
## reorder species groups for plot
x$species_group <- factor(x$species_group, levels = sefra_data[['species_groups']])
## Restructure to have observed captures as a variable
tab_dat <- x %>%
filter(., name %in% "emp") %>%
select(., fishery_group, code, obs = mean)
tab_dat <- x %>% filter(., !name %in% "emp") %>%
left_join(tab_dat, ., by = c("fishery_group", "code"))
## Combine estimate and 95% CI
tab_dat <- tab_dat %>% mutate(., est = paste0(round(mean, 1), " (", round(lq, 1), "-", round(uq, 1), ")"))
tab_dat <- tab_dat %>% tidyr::pivot_wider(id_cols = code, values_from = c('obs', 'est'), names_from = fishery_group) %>%
arrange(., code)
## Add species names
tab_dat <- species_names(sefra_data) %>% select(., code, common_name) %>%
left_join(tab_dat, ., by = "code")
## Species
# filter
tab_dat <- tab_dat %>% filter(!code %in% codes_exclude)
## Reorder variables
tab_dat <- tab_dat %>% select('code', contains('DOM'), contains('JV'), contains('JPN'), contains('TWN'))
tab <- kable(tab_dat, format = 'latex',
col.names = c('', rep(c('Observed', 'Estimated'), times = sefra_data$n_fishery_groups)),
row.names = FALSE,
caption = "Fit to (cumulative) captures by capture code and fishery group.",
label = 'fit_captures_by_code_fishery_group',
align = c('l', rep('r', times = ncol(tab_dat) - 1)),
linesep = "", booktabs = TRUE) %>%
add_header_above(c("Code", "NZL (DOM)" = 2, "NZL (JV)" = 2, "JPN" = 2, "TWN" = 2), align = c('l', 'c', 'c', 'c', 'c')) %>%
kable_styling(font_size = 10, latex_options = "hold_position") %>%
sub("\\\\cmidrule\\(l\\{3pt\\}r\\{3pt\\}\\)\\{1-1\\}", "", .) %>%
sub("\\\\toprule", "", .) %>%
sub("\\\\bottomrule", "", .)
save_kable(tab, file = file.path(output_path, "tables", "fit_captures_per_code_fishery_group.tex"))
write.csv(tab_dat, file = file.path(output_path, "tables", "fit_captures_per_code_fishery_group.csv"))
Observed | Estimated | Observed | Estimated | Observed | Estimated | Observed | Estimated | |
---|---|---|---|---|---|---|---|---|
DKS | 1 | 17.8 (9-27) | 0 | 1.8 (0-5) | 0 | 20.9 (11-31) | 8 | 1.8 (0-5) |
DER | 0 | 0.9 (0-3) | 0 | 0 (0-0) | 3 | 4.6 (1-9) | 0 | 0.2 (0-1) |
DIC | 1 | 0.4 (0-2) | 0 | 0.1 (0-1) | 840 | 772.9 (699-851) | 17 | 84.7 (63-106) |
PHU | 0 | 0 (0-0) | 0 | 0 (0-0) | 134 | 141.2 (111-172) | 61 | 57.8 (38-81) |
PHE | 0 | 0.9 (0-4) | 0 | 0.5 (0-3) | 95 | 75.2 (54-99) | 6 | 11.2 (5-20) |
PCI | 4 | 32.6 (19-48) | 0 | 0.8 (0-3) | 152 | 101 (77-127) | 3 | 10.8 (5-18) |
PCN | 0 | 0 (0-0) | 0 | 0 (0-0) | 44 | 28.1 (17-41) | 53 | 39.3 (25-57) |
DRA | 11 | 11.2 (3-22) | 0 | 0.6 (0-3) | 21 | 21.4 (10-35) | 4 | 4.1 (0-11) |
DYN | 0 | 0 (0-0) | 0 | 0 (0-0) | 205 | 302.6 (260-353) | 148 | 70.7 (53-91) |
DST | 151 | 101.6 (79-124) | 11 | 33.4 (20-49) | 796 | 807.6 (735-880) | 38 | 41 (28-55) |
DBB | 14 | 74.3 (56-93) | 1 | 8.1 (3-15) | 783 | 708.4 (638-781) | 113 | 115.7 (91-141) |
DIB | 125 | 85.6 (66-106) | 62 | 20.3 (11-32) | 789 | 811.9 (740-889) | 4 | 29.7 (19-42) |
DWC | 27 | 26.6 (14-43) | 0 | 0.8 (0-4) | 342 | 341.5 (293-392) | 54 | 55.5 (38-77) |
PRZ | 81 | 49.1 (31-69) | 2 | 1.7 (0-5) | 416 | 478.5 (424-539) | 191 | 169 (138-204) |
DIZ | 40 | 38.1 (22-57) | 0 | 1.3 (0-5) | 389 | 387.4 (335-441) | 58 | 62.4 (42-84) |
THZ | 292 | 284.7 (242-331) | 74 | 67.6 (46-90) | 3683 | 3648.9 (3479-3816) | 328 | 357.8 (308-410) |
PHZ | 0 | 0.8 (0-4) | 0 | 0.5 (0-3) | 233 | 230.1 (189-274) | 67 | 72.2 (50-98) |
PTZ | 85 | 82.7 (59-110) | 2 | 2.5 (0-7) | 612 | 646.6 (580.9-712) | 272 | 226.7 (189-269) |
ALZ | 332 | 328 (279-380) | 74 | 71.8 (49-97) | 5127 | 5124.5 (4925-5324) | 623 | 618.6 (552.9-690) |
PRX | 85 | 83.6 (58-110) | 2 | 2.7 (0-8) | 777 | 778 (701.9-855) | 286 | 286.7 (241-338) |
BLZ | 417 | 416.4 (362-470) | 76 | 79.2 (56-104) | 6127 | 6127.9 (5916-6340.1) | 917 | 917.2 (837-1004) |
Estimated catchabilities (log-scale):
x <- rstan::extract(mdl_fit, pars = "q", permute = FALSE)
dimnames(x) <- list(iteration = 0.5 * n_iter + (1:dim(x)[1]), chain = paste0("chain_", 1:dim(x)[2]),
parameter = dimnames(x)[[3]])
x <- reshape2::melt(x)
x <- x %>% group_by(., parameter) %>%
summarise(., mean = mean(value), low_ci = quantile(value, prob = 0.025), high_ci = quantile(value, prob = 0.975)) %>%
ungroup(.) %>%
mutate(., across(c(mean, low_ci, high_ci), log10))
kable(x, digits = 2)
parameter | mean | low_ci | high_ci |
---|---|---|---|
q[1,1] | 0.71 | 0.52 | 0.88 |
q[2,1] | -1.28 | -2.10 | -0.79 |
q[3,1] | 1.14 | 1.05 | 1.22 |
q[4,1] | 0.54 | 0.40 | 0.66 |
q[1,2] | 0.48 | 0.11 | 0.75 |
q[2,2] | -1.08 | -2.17 | -0.53 |
q[3,2] | 0.88 | 0.60 | 1.12 |
q[4,2] | 0.48 | -0.05 | 0.84 |
q[1,3] | 0.48 | 0.41 | 0.55 |
q[2,3] | -0.47 | -0.60 | -0.35 |
q[3,3] | 0.90 | 0.83 | 0.97 |
q[4,3] | 0.02 | -0.05 | 0.09 |
q[1,4] | 0.06 | -0.90 | 0.57 |
q[2,4] | -1.00 | -1.99 | -0.47 |
q[3,4] | 1.21 | 1.11 | 1.31 |
q[4,4] | 0.72 | 0.57 | 0.85 |
q[1,5] | 0.51 | 0.35 | 0.65 |
q[2,5] | -1.30 | -1.88 | -0.93 |
q[3,5] | 0.76 | 0.67 | 0.83 |
q[4,5] | 0.01 | -0.09 | 0.09 |
Table of catchability estimates for reporting:
x <- rstan::extract(mdl_fit, pars = "q", permute = TRUE)[[1]]
dimnames(x) <- list(iteration = 0.5 * n_iter + (1:dim(x)[1]), fishery_group = sefra_data$fishery_groups,
species_group = sefra_data$species_groups)
x <- reshape2::melt(x) %>% group_by(fishery_group, species_group) %>% summarise(., mean = mean(value), low_ci = quantile(value, prob = 0.025), high_ci = quantile(value, prob = 0.975)) %>% ungroup(.)
## `summarise()` has grouped output by 'fishery_group'. You can override using the
## `.groups` argument.
x <- x %>% tidyr::pivot_wider(values_from = c('mean', 'low_ci', 'high_ci'), names_from = fishery_group)
x <- x %>% select('species_group', contains('DOM'), contains('JV'), contains('JPN'), contains('TWN'))
tab <- kable(x, format = 'latex',
digits = 2,
col.names = c('', rep(c('mean', 'low', 'upp'), times = sefra_data$n_fishery_groups)),
row.names = FALSE,
caption = "Catchability",
label = 'q_per_species_group_fishery_group',
align = c('l', rep('r', times = ncol(x) - 1)),
linesep = "", booktabs = TRUE) %>% kable_styling(font_size = 10, latex_options = "hold_position")
if (grepl("combined", output_path)) {
tab <- tab %>% add_header_above(c("Year", "NZL (DOM)" = 2, "NZL (JV)" = 2, "JPN" = 2, "TWN" = 2), align = c('l', rep('c', times = sefra_data$n_fishery_groups))) %>% sub("\\\\cmidrule\\(l\\{3pt\\}r\\{3pt\\}\\)\\{1-1\\}", "", .)
}
if (grepl("nzl", output_path)) {
tab <- tab %>% add_header_above(c("Year", "NZL (DOM)" = 2, "NZL (JV)" = 2), align = c('l', rep('c', times = sefra_data$n_fishery_groups))) %>% sub("\\\\cmidrule\\(l\\{3pt\\}r\\{3pt\\}\\)\\{1-1\\}", "", .)
}
if (grepl("jpn", output_path)) {
tab <- tab %>% add_header_above(c("Year", "JPN" = 2), align = c('l', rep('c', times = sefra_data$n_fishery_groups))) %>% sub("\\\\cmidrule\\(l\\{3pt\\}r\\{3pt\\}\\)\\{1-1\\}", "", .)
}
if (grepl("twn", output_path)) {
tab <- tab %>% add_header_above(c("Year", "TWN" = 2), align = c('l', rep('c', times = sefra_data$n_fishery_groups))) %>% sub("\\\\cmidrule\\(l\\{3pt\\}r\\{3pt\\}\\)\\{1-1\\}", "", .)
}
tab <- tab %>%
sub("\\\\toprule", "", .) %>%
sub("\\\\bottomrule", "", .)
save_kable(tab, file = file.path(output_path, "tables", "q_per_species_group_fishery_group.tex"))
write.csv(x, file = file.path(output_path, "tables", "q_per_species_group_fishery_group.csv"))
Table of catchability estimates with CI in brackets:
x <- rstan::extract(mdl_fit, pars = "q", permute = TRUE)[[1]]
dimnames(x) <- list(iteration = 0.5 * n_iter + (1:dim(x)[1]), fishery_group = sefra_data$fishery_groups,
species_group = sefra_data$species_groups)
x <- reshape2::melt(x) %>% group_by(fishery_group, species_group) %>% summarise(., mean = mean(value), low_ci = quantile(value, prob = 0.025), high_ci = quantile(value, prob = 0.975)) %>% ungroup(.)
## `summarise()` has grouped output by 'fishery_group'. You can override using the
## `.groups` argument.
x <- x %>% mutate(., value = paste0(round(mean, 2), " (", round(low_ci, 2), "-", round(high_ci, 2), ")"))
x <- x %>% tidyr::pivot_wider(id_cols = species_group, values_from = value, names_from = fishery_group)
tab <- kable(x, format = 'latex',
col.names = stringr::str_to_sentence(colnames(x)),
row.names = FALSE,
caption = "Catchability",
label = 'q_per_species_group_fishery_group',
align = c('l', rep('r', times = ncol(x) - 1)),
linesep = "", booktabs = TRUE) %>%
kable_styling(font_size = 10, latex_options = "hold_position") %>%
sub("\\\\toprule", "", .) %>%
sub("\\\\bottomrule", "", .)
save_kable(tab, file = file.path(output_path, "tables", "q_per_species_group_fishery_group_alternative.tex"))
write.csv(x, file = file.path(output_path, "tables", "q_per_species_group_fishery_group_alternative.csv"))
Species_group | Nzl (dom) | Nzl (jv) | Jpn | Twn |
---|---|---|---|---|
Wandering albatross | 5.18 (3.3-7.51) | 0.05 (0.01-0.16) | 13.85 (11.32-16.51) | 3.44 (2.52-4.62) |
Royal albatross | 2.99 (1.28-5.6) | 0.08 (0.01-0.3) | 7.6 (3.99-13.24) | 3.05 (0.9-6.88) |
Mollymawk | 3.04 (2.56-3.58) | 0.34 (0.25-0.45) | 7.96 (6.82-9.23) | 1.05 (0.9-1.23) |
Sooty albatross | 1.14 (0.13-3.72) | 0.1 (0.01-0.34) | 16.1 (12.76-20.61) | 5.21 (3.73-7.1) |
Medium petrel | 3.23 (2.23-4.45) | 0.05 (0.01-0.12) | 5.71 (4.69-6.83) | 1.01 (0.82-1.23) |
Table of alpha_fishery_group
coefficients (adjusted by
alpha_intercept
):
alpha_0 <- rstan::extract(mdl_fit, pars = "alpha_intercept", permute = TRUE)[[1]]
dimnames(alpha_0) <- list(iteration = 0.5 * n_iter + (1:dim(alpha_0)[1]), fishery_group = sefra_data$fishery_groups)
alpha_fg <- rstan::extract(mdl_fit, pars = "alpha_fishery_group", permute = TRUE)[[1]]
dimnames(alpha_fg) <- list(iteration = 0.5 * n_iter + (1:dim(alpha_fg)[1]), fishery_group = sefra_data$fishery_groups)
# take sum of catchability intercept and fishery group coefficients
# and (back)transform to nominal scale
alpha_fg_adj <- alpha_0 + alpha_fg
alpha_fg_adj <- exp(alpha_fg_adj)
alpha_fg_adj <- reshape2::melt(alpha_fg_adj)
tab_dat <- alpha_fg_adj %>% group_by(fishery_group) %>% summarise(., mean = mean(value), low_ci = quantile(value, prob = 0.025), high_ci = quantile(value, prob = 0.975)) %>% ungroup(.)
tab_dat <- tab_dat %>% mutate(., alpha_fg = paste0(round(mean, 2), " (", round(low_ci, 2), "-", round(high_ci, 2), ")"))
tab <- kable(tab_dat %>% select(., fishery_group, alpha_fg), format = 'latex',
col.names = c("Fishery group", "alpha_fishery_group"),
row.names = FALSE,
caption = "Catchability coefficients per fishery group.",
label = 'catchability_coefficients_fishery_group',
align = c('l', rep('r', times = ncol(tab_dat) - 1)),
linesep = "", booktabs = TRUE) %>%
kable_styling(font_size = 10, latex_options = "hold_position") %>%
sub("\\\\toprule", "", .) %>%
sub("\\\\bottomrule", "", .)
save_kable(tab, file = file.path(output_path, "tables", "catchability_coefficients_fishery_group.tex"))
write.csv(tab_dat, file = file.path(output_path, "tables", "catchability_coefficients_fishery_group.csv"))
Fishery group | alpha_fishery_group |
---|---|
NZL (DOM) | 2.63 (1.73-3.69) |
NZL (JV) | 0.08 (0.03-0.15) |
JPN | 9.39 (8.06-10.85) |
TWN | 2.2 (1.73-2.69) |
Catchability intercept:
x <- rstan::extract(mdl_fit, pars = "alpha_intercept", permute = FALSE)
dimnames(x) <- list(iteration = 0.5 * n_iter + (1:dim(x)[1]), chain = paste0("chain_", 1:dim(x)[2]),
parameter = dimnames(x)[[3]])
x <- reshape2::melt(x)
x <- x %>% group_by(., parameter) %>%
summarise(., mean = mean(value), low_ci = quantile(value, prob = 0.025), high_ci = quantile(value, prob = 0.975)) %>%
ungroup(.)
kable(x, digits = 2)
parameter | mean | low_ci | high_ci |
---|---|---|---|
alpha_intercept[1] | 0.34 | 0.09 | 0.57 |
alpha_intercept[2] | 0.34 | 0.09 | 0.57 |
alpha_intercept[3] | 0.34 | 0.09 | 0.57 |
alpha_intercept[4] | 0.34 | 0.09 | 0.57 |
Fishery group catchability parameters:
x <- rstan::extract(mdl_fit, pars = "alpha_fishery_group", permute = FALSE)
dimnames(x) <- list(iteration = 0.5 * n_iter + (1:dim(x)[1]), chain = paste0("chain_", 1:dim(x)[2]),
parameter = dimnames(x)[[3]])
x <- reshape2::melt(x)
x <- x %>% group_by(., parameter) %>%
summarise(., mean = mean(value), low_ci = quantile(value, prob = 0.025), high_ci = quantile(value, prob = 0.975)) %>%
ungroup(.)
kable(x, digits = 2)
parameter | mean | low_ci | high_ci |
---|---|---|---|
alpha_fishery_group[1] | 0.61 | 0.24 | 0.97 |
alpha_fishery_group[2] | -2.95 | -3.61 | -2.40 |
alpha_fishery_group[3] | 1.90 | 1.68 | 2.13 |
alpha_fishery_group[4] | 0.44 | 0.19 | 0.70 |
Species group catchability parameters
x <- rstan::extract(mdl_fit, pars = "alpha_species_group", permute = FALSE)
dimnames(x) <- list(iteration = 0.5 * n_iter + (1:dim(x)[1]), chain = paste0("chain_", 1:dim(x)[2]),
parameter = dimnames(x)[[3]])
x <- reshape2::melt(x)
x <- x %>% group_by(., parameter) %>%
summarise(., mean = mean(value), low_ci = quantile(value, prob = 0.025), high_ci = quantile(value, prob = 0.975)) %>%
ungroup(.)
kable(x, digits = 2)
parameter | mean | low_ci | high_ci |
---|---|---|---|
alpha_species_group[1,1] | 0.68 | 0.18 | 1.17 |
alpha_species_group[2,1] | -0.62 | -1.88 | 0.58 |
alpha_species_group[3,1] | 0.39 | 0.15 | 0.59 |
alpha_species_group[4,1] | 0.44 | 0.11 | 0.79 |
alpha_species_group[1,2] | 0.08 | -0.61 | 0.75 |
alpha_species_group[2,2] | -0.27 | -1.97 | 1.12 |
alpha_species_group[3,2] | -0.26 | -0.74 | 0.21 |
alpha_species_group[4,2] | 0.21 | -0.71 | 0.97 |
alpha_species_group[1,3] | 0.16 | -0.23 | 0.59 |
alpha_species_group[2,3] | 1.53 | 0.78 | 2.39 |
alpha_species_group[3,3] | -0.16 | -0.35 | 0.02 |
alpha_species_group[4,3] | -0.74 | -0.97 | -0.48 |
alpha_species_group[1,4] | -1.13 | -2.65 | 0.08 |
alpha_species_group[2,4] | -0.09 | -1.67 | 1.28 |
alpha_species_group[3,4] | 0.53 | 0.31 | 0.80 |
alpha_species_group[4,4] | 0.86 | 0.53 | 1.22 |
alpha_species_group[1,5] | 0.21 | -0.24 | 0.69 |
alpha_species_group[2,5] | -0.54 | -1.58 | 0.50 |
alpha_species_group[3,5] | -0.50 | -0.71 | -0.29 |
alpha_species_group[4,5] | -0.77 | -1.02 | -0.48 |
Recover estimated catchabilities from model parameters:
## Get catchability parameters
qq <- rstan::extract(mdl_fit, pars = "q", permute = TRUE)[[1]]
dimnames(qq) <- list(iteration = 0.5 * n_iter + (1:dim(qq)[1]), fishery_group = sefra_data$fishery_groups,
species_group = sefra_data$species_groups)
qq <- reshape2::melt(qq) %>% rename(., q = value)
## beta_0 (intercept - same for all fishery groups)
b_0 <- rstan::extract(mdl_fit, pars = "alpha_intercept", permute = TRUE)[[1]]
dimnames(b_0) <- list(iteration = 0.5 * n_iter + (1:dim(b_0)[1]), fishery_group = sefra_data$fishery_groups)
b_0 <- reshape2::melt(b_0) %>% rename(., b_0 = value)
## beta_f
b_f <- rstan::extract(mdl_fit, pars = "alpha_fishery_group", permute = TRUE)[[1]]
dimnames(b_f) <- list(iteration = 0.5 * n_iter + (1:dim(b_f)[1]), fishery_group = sefra_data$fishery_groups)
b_f <- reshape2::melt(b_f) %>% rename(., b_f = value)
## beta_fg
b_fg <- rstan::extract(mdl_fit, pars = "alpha_species_group", permute = TRUE)[[1]]
dimnames(b_fg) <- list(iteration = 0.5 * n_iter + (1:dim(b_fg)[1]), fishery_group = sefra_data$fishery_groups,
species_group = sefra_data$species_groups)
b_fg <- reshape2::melt(b_fg) %>% rename(., b_fg = value)
## combine betas and recover q
qq_test <- b_fg
qq_test <- b_f %>% left_join(qq_test, ., by = c("iteration", "fishery_group"))
qq_test <- b_0 %>% left_join(qq_test, ., by = c("iteration", "fishery_group"))
qq_test <- qq_test %>% mutate(., q = exp(b_0 + b_f + b_fg))
## check recovered q is equal to that provided by the model
all.equal(qq$q, qq_test$q)
## [1] TRUE
pi
parameterspi
parameters estimate the probability of identifying
captures of a specific taxa to different taxonomic resolutions.
Estimated pi
parameters:
# transfrom from logit to probabilities
inv_logit <- binomial()$linkinv
plt_dat <- out[["p_obs_logit"]]
plt_dat <- plt_dat %>% mutate(., value = inv_logit(value))
# rescale to sum to 1
plt_dat <- plt_dat %>% group_by(., iter, fishery_group, pi) %>%
mutate(., value = value / sum(value)) %>% ungroup(.)
plt_dat <- plt_dat %>%
group_by(., fishery_group, pi, resolution) %>%
summary_fn_boxplot(., value) %>% ungroup()
## `summarise()` has grouped output by 'fishery_group', 'pi'. You can override
## using the `.groups` argument.
if(length(levels(plt_dat$pi)) == 1) {
gg <- plt_dat %>%
ggplot() +
geom_boxplot(aes(x = fishery_group, ymin = lq, lower = lmq, middle = mq, upper = umq, ymax = uq, fill = resolution), stat = "identity", width = 0.75) +
coord_cartesian(ylim = c(0, NA)) +
scale_fill_manual("Taxonomic\nresolution", values = cols_taxo_resolution) +
theme_bw(base_size = 12) +
theme(legend.position = "right") +
labs(x = "Fisheries group", y = "Probability of taxonomic resolutions for capture identifications")
print(gg)
ggsave(gg, file = file.path(output_path, "figures", "pi_boxplot.png"), width = 8, height = 6)
ggsave(gg, file = file.path(output_path, "figures", "pi_boxplot.pdf"), width = 8, height = 6)
}
if(length(levels(plt_dat$pi)) > 1) {
for(i in 1:length(fg_group_levels)) {
gg <- plt_dat %>%
filter(., fishery_group %in% fg_group_levels[i]) %>%
ggplot() + geom_boxplot(aes(x = pi, ymin = lq, lower = lmq, middle = mq, upper = umq, ymax = uq, fill = resolution), stat = "identity", width = 0.75) +
facet_wrap(vars(fishery_group)) +
coord_cartesian(ylim = c(0, NA)) +
scale_fill_manual("Taxonomic\nresolution", values = cols_taxo_resolution) +
theme_bw(base_size = 12) +
theme(legend.position = "right") +
labs(x = "Pi group", y = "Probability of taxonomic resolutions")
print(gg)
ggsave(gg, file = file.path(output_path, "figures", paste0("pi_boxplot_fishery_", i, ".png")), width = 8, height = 6)
ggsave(gg, file = file.path(output_path, "figures", paste0("pi_boxplot_fishery_", i, ".pdf")), width = 8, height = 6)
}
}
Estimated catchabilities (log-scale):
x <- rstan::extract(mdl_fit, pars = "q", permute = TRUE)[[1]]
dimnames(x) <- list(iteration = 0.5 * n_iter + (1:dim(x)[1]), fishery_group = sefra_data$fishery_groups,
species_group = sefra_data$species_groups)
x <- reshape2::melt(x)
plt_dat <- x %>% group_by(., fishery_group, species_group) %>%
summarise(., mean = mean(value), mq = median(value),
lq = as.numeric(quantile(value, probs = 0.025)),
uq = as.numeric(quantile(value, probs = 0.975))) %>% ungroup()
## `summarise()` has grouped output by 'fishery_group'. You can override using the
## `.groups` argument.
gg <- plt_dat %>%
ggplot(aes(x = species_group, y = mq, col = species_group)) +
geom_pointrange(aes(ymin = lq, ymax = uq), alpha = 0.75, size = 0.75, linewidth = 0.75) +
scale_colour_manual("", values = cols_species_group) +
facet_wrap(fishery_group ~ ., ncol = 1) +
scale_x_discrete(guide = guide_axis(n.dodge = 2)) +
theme_bw(base_size = 12) +
theme(legend.position = "none") +
labs(x = "Species group", y = "Estimated catchability (q)") +
scale_y_log10()
gg
ggsave(gg, file = file.path(output_path, "figures", "log10_catchabilities.png"), width = 6, height = 10)
ggsave(gg, file = file.path(output_path, "figures", "log10_catchabilities.pdf"), width = 6, height = 10)
Boxplot of estimated catchabilities (natural-scale):
x <- rstan::extract(mdl_fit, pars = "q", permute = TRUE)[[1]]
dimnames(x) <- list(iteration = 0.5 * n_iter + (1:dim(x)[1]), fishery_group = sefra_data$fishery_groups,
species_group = sefra_data$species_groups)
x <- reshape2::melt(x)
plt_dat <- x %>% group_by(., fishery_group, species_group) %>%
summary_fn_boxplot(., value) %>% ungroup()
## `summarise()` has grouped output by 'fishery_group'. You can override using the
## `.groups` argument.
gg <- plt_dat %>%
ggplot() +
geom_boxplot(aes(x = fishery_group, ymin = lq, lower = lmq, middle = mq, upper = umq, ymax = uq, fill = species_group), stat = "identity", width = 0.75) +
scale_fill_manual("Species group", values = cols_species_group) +
theme_bw(base_size = 12) +
theme(legend.position = "right") +
labs(x = "Fisheries group", y = "Estimated catchability (q)")
gg
ggsave(gg, file = file.path(output_path, "figures", "catchabilities_boxplot.png"), width = 8, height = 6)
ggsave(gg, file = file.path(output_path, "figures", "catchabilities_boxplot.pdf"), width = 8, height = 6)
Boxplot of estimated catchabilities (log-scale):
gg <- plt_dat %>%
ggplot() +
geom_boxplot(aes(x = fishery_group, ymin = lq, lower = lmq, middle = mq, upper = umq, ymax = uq, fill = species_group), stat = "identity", width = 0.75) +
scale_fill_manual("Species group", values = cols_species_group) +
theme_bw(base_size = 12) +
theme(legend.position = "right") +
labs(x = "Fisheries group", y = "Estimated catchability (q)") +
scale_y_log10()
gg
ggsave(gg, file = file.path(output_path, "figures", "log10_catchabilities_boxplot.png"), width = 8, height = 6)
ggsave(gg, file = file.path(output_path, "figures", "log10_catchabilities_boxplot.pdf"), width = 8, height = 6)
Estimated catchabilities per fleet (log-scale):
x <- rstan::extract(mdl_fit, pars = "alpha_fishery_group", permute = TRUE)[[1]]
dimnames(x) <- list(iteration = 0.5 * n_iter + (1:dim(x)[1]), fishery_group = sefra_data$fishery_groups)
x <- reshape2::melt(x)
plt_dat <- x %>% group_by(., fishery_group) %>%
summarise(., mean = mean(value), mq = median(value),
lq = as.numeric(quantile(value, probs = 0.025)),
uq = as.numeric(quantile(value, probs = 0.975))) %>% ungroup()
gg <- plt_dat %>%
ggplot(aes(x = fishery_group, y = mq, col = fishery_group)) +
geom_pointrange(aes(ymin = lq, ymax = uq), alpha = 0.75, size = 0.75, linewidth = 0.75) +
theme_bw(base_size = 12) +
theme(legend.position = "none") +
labs(x = "Fishery group", y = "Estimated catchability coefficient")
gg
Maps of density overlap:
dfr <- out[["map_overlap"]]
dfr <- dfr %>% mutate(., cell = as.numeric(as.character(cell)))
## Sum overlap across species group (by fishery group)
dfr <- species_groups(sefra_data, print_species = TRUE) %>% select(., species, species_group) %>%
left_join(dfr, .)
## 5 species groups
## (with 25 species)
## Joining with `by = join_by(species)`
dfr <- dfr %>% group_by(., fishery_group, species_group, cell) %>%
summarise(., value = sum(value)) %>% data.frame(.)
## `summarise()` has grouped output by 'fishery_group', 'species_group'. You can
## override using the `.groups` argument.
## Factorise species groups for appropriate ordering
dfr <- dfr %>% mutate(., species_group = factor(species_group, levels = sefra_data$species_groups))
## Include spatial information
dfr <- dfr %>% left_join(., grid, by = c("cell" = "id_cell")) %>% st_as_sf()
dfr <- dfr %>% filter(., value > 0)
gg <- ggplot() +
geom_sf(data = dfr, aes(fill = as.numeric(value)), col = NA, size = NA) +
facet_grid(species_group ~ fishery_group) +
#geom_sf(data = grid, fill = NA, size = NA) +
geom_sf(data = southern_map, fill = "grey") +
coord_sf(xlim = southern_bbox[c(1, 3)], ylim = southern_bbox[c(2, 4)], expand = FALSE) +
#guides(fill = "none") +
labs(fill = "Density\nOverlap") +
viridis::scale_fill_viridis(direction = -1, trans = "log10") +
theme_bw() +
theme(axis.title = element_blank(),
legend.position = "bottom",
legend.key.width = unit(1.5, "cm"),
axis.text = element_blank(),
axis.ticks = element_blank(),
plot.background = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
strip.text = element_text(size = 10))
gg
## Saving 8 x 12 in image
## Saving 8 x 12 in image
map_caption <- paste0("Map of estimated density overlap from observed effort, by species group and fishery group.")
write(paste0("\\caption{", map_caption, "}"), file = file.path(output_path, "maps", "density_overlap_caption.tex"))
Maps of predicted and observed captures. The model predicts captures per species. These captures are down-weighted according to the probability of observation, to allow comparison with the observations.
# map of the overlap and captures per species and fishery group
x <- out[["map_capture"]] %>% group_by(cell, fishery_group, species) %>% summarise(value = sum(value)) %>% ungroup() %>% mutate(id_cell = as.integer(as.character(cell)))
x <- x %>% left_join(grid, by = "id_cell") %>% filter(value > 0)
y <- captures_o %>% filter(id_species %in% 1:27) %>% group_by(id_cell, fishery_group, code) %>% summarise(n_captures = sum(n_captures)) %>% ungroup()
y <- y %>% filter(n_captures > 0)
dfr <- full_join(x, y, by = c("id_cell" = "id_cell", "species" = "code", "fishery_group" = "fishery_group")) %>% filter(!is.na(value)) %>% mutate(n_captures = replace_na(n_captures, 0))
dfr <- dfr %>% st_as_sf()
# maps per species
df1 <- split(dfr, ~species)
for (i in names(df1)) {
dfr_captures_sim <- df1[[i]]
dfr_captures_emp <- df1[[i]] %>% st_centroid() %>% filter(n_captures > 0)
dfr_caption <- dfr_captures_emp %>% group_by(fishery_group) %>% summarise(n_captures = sum(n_captures)) %>% st_drop_geometry()
dfr_caption <- purrr::map2(dfr_caption$fishery_group, dfr_caption$n_captures, function(x, y) paste0(x, " = ", y)) %>% unlist() %>% paste(collapse = ", ")
map_caption <- paste0("Map of the sum of the observed and predicted captures per fishery group for ", i, ". Total captures per fishery group are: ", ifelse(dfr_caption == "", "0", dfr_caption), ".")
map_label <- paste0("captures_emp_vs_sim_per_species_", i)
write(paste0("\\caption{", map_caption, "}"), file = file.path(output_path, "maps", paste0(map_label, "_caption.tex")))
gg <- ggplot() +
geom_sf(data = dfr_captures_sim, aes(fill = value), col = NA) +
geom_sf(data = dfr_captures_emp, aes(size = n_captures, alpha = n_captures), col = "tomato") +
facet_wrap(~fishery_group) + theme_sh() + scale_fill_viridis(direction = -1) +
labs(fill = "Predicted\nCaptures", size = "Observed\nCaptures") + guides(alpha = "none")
ggfile <- file.path(output_path, "maps", paste0(map_label, ".png"))
ggsave(gg, file = ggfile)
}
Maps of deaths:
dfr <- out[["map_deaths"]]
dfr <- dfr %>% mutate(., cell = as.numeric(as.character(cell)))
## Sum deaths across species group (by fishery group)
dfr <- species_groups(sefra_data, print_species = TRUE) %>% select(., species, species_group) %>%
left_join(dfr, .)
## 5 species groups
## (with 25 species)
## Joining with `by = join_by(species)`
dfr <- dfr %>% group_by(., fishery_group, species_group, cell) %>%
summarise(., value = sum(value)) %>% data.frame(.)
## `summarise()` has grouped output by 'fishery_group', 'species_group'. You can
## override using the `.groups` argument.
## Factorise species groups for appropriate ordering
dfr <- dfr %>% mutate(., species_group = factor(species_group, levels = sefra_data$species_groups))
## Include spatial information
dfr <- dfr %>% left_join(., grid, by = c("cell" = "id_cell")) %>% st_as_sf()
dfr <- dfr %>% filter(., value > 0)
gg <- ggplot() +
geom_sf(data = dfr, aes(fill = as.numeric(value)), col = NA, size = NA) +
facet_grid(species_group ~ fishery_group) +
#geom_sf(data = grid, fill = NA, size = NA) +
geom_sf(data = southern_map, fill = "grey") +
coord_sf(xlim = southern_bbox[c(1, 3)], ylim = southern_bbox[c(2, 4)], expand = FALSE) +
#guides(fill = "none") +
labs(fill = "Deaths") +
viridis::scale_fill_viridis(direction = -1, trans = "log10", option = "inferno") +
theme_bw() +
theme(axis.title = element_blank(),
legend.position = "bottom",
legend.key.width = unit(1.5, "cm"),
axis.text = element_blank(),
axis.ticks = element_blank(),
plot.background = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
strip.text = element_text(size = 10))
gg
## Saving 8 x 12 in image
## Saving 8 x 12 in image
map_caption <- paste0("Map of estimated deaths resulting from observed fishing effort, by species group and fishery group.")
write(paste0("\\caption{", map_caption, "}"), file = file.path(output_path, "maps", "deaths_caption.tex"))
## used (Mb) gc trigger (Mb) max used (Mb)
## Ncells 4219180 225.4 9251123 494.1 9251123 494.1
## Vcells 13003981 99.3 2772971320 21156.1 4158397728 31726.1