4 Nutritional profiles
Code
library(ggplot2)
data <- get_model_data()
data$data_raw$timor_GN_raw$clusters <- paste0("FNP-", data$data_raw$timor_GN_raw$clusters)
data$data_raw$timor_AG_raw$clusters <- paste0("FNP-", data$data_raw$timor_AG_raw$clusters)
plot_profiles <- function(x) {
means_dat <-
x %>%
dplyr::rename_with(~ stringr::str_to_title(.x), .cols = c(.data$zinc:.data$vitaminA)) %>%
dplyr::rename(
"Vitamin-A" = .data$Vitamina,
"Omega-3" = .data$Omega3
) %>%
tidyr::pivot_longer(c(Zinc:"Vitamin-A")) %>%
dplyr::group_by(clusters, name) %>%
dplyr::summarise(
mean = mean(value, na.rm = TRUE),
sd = sd(value, na.rm = TRUE),
n = dplyr::n(),
se = sd / sqrt(n),
ci_lower = mean - qt(0.99, df = n - 1) * se,
ci_upper = mean + qt(0.99, df = n - 1) * se
)
all_dat <-
x %>%
dplyr::rename_with(~ stringr::str_to_title(.x), .cols = c(.data$zinc:.data$vitaminA)) %>%
dplyr::rename(
"Vitamin-A" = .data$Vitamina,
"Omega-3" = .data$Omega3
) %>%
tidyr::pivot_longer(c(Zinc:"Vitamin-A"))
ggplot() +
ggpubr::theme_pubr()+
geom_jitter(data = all_dat, mapping = aes(x = value, y = name, color = clusters), alpha = 0.01, size = 1, position = position_dodge(width = 0.5)) +
geom_point(data = means_dat, mapping = aes(x = mean, y = name, color = clusters), size = 5, position = position_dodge(width = 0.5)) +
labs(
x = "",
y = "",
color = "Profiles"
) +
ggplot2::theme(
legend.position = "",
plot.margin = unit(c(0, 0, 0, 0), "cm"),
panel.grid = ggplot2::element_blank()
) +
coord_cartesian(xlim = c(0, 5)) +
scale_fill_manual(values = timor.nutrients::palettes$clusters_palette) +
scale_color_manual(values = timor.nutrients::palettes$clusters_palette)
}
plots1 <- plot_profiles(data$data_raw$timor_AG_raw) #purrr::map(data$data_raw$timor_AG_raw, plot_profiles)
means_dat <-
data$data_raw$timor_GN_raw %>%
dplyr::rename_with(~ stringr::str_to_title(.x), .cols = c(.data$zinc:.data$vitaminA)) %>%
dplyr::rename(
"Vitamin-A" = .data$Vitamina,
"Omega-3" = .data$Omega3
) %>%
tidyr::pivot_longer(c(Zinc:"Vitamin-A")) %>%
dplyr::group_by(clusters, name) %>%
dplyr::summarise(
mean = mean(value, na.rm = TRUE),
sd = sd(value, na.rm = TRUE),
n = dplyr::n(),
se = sd / sqrt(n),
ci_lower = mean - qt(0.99, df = n - 1) * se,
ci_upper = mean + qt(0.99, df = n - 1) * se
)
all_dat <-
data$data_raw$timor_GN_raw %>%
dplyr::rename_with(~ stringr::str_to_title(.x), .cols = c(.data$zinc:.data$vitaminA)) %>%
dplyr::rename(
"Vitamin-A" = .data$Vitamina,
"Omega-3" = .data$Omega3
) %>%
tidyr::pivot_longer(c(Zinc:"Vitamin-A"))
plots2 <-
ggplot() +
ggpubr::theme_pubr()+
geom_jitter(data = all_dat, mapping = aes(x = value, y = name, color = clusters), alpha = 0.01, size = 1, position = position_dodge(width = 0.5)) +
geom_point(data = means_dat, mapping = aes(x = mean, y = name, color = clusters), size = 5, position = position_dodge(width = 0.5)) +
labs(
x = "",
y = "",
color = "Profiles"
) +
ggplot2::theme(
legend.position = "",
plot.margin = unit(c(0, 0, 0, 0), "cm"),
panel.grid = ggplot2::element_blank()
) +
coord_cartesian(xlim = c(0, 5)) +
scale_fill_manual(values = timor.nutrients::palettes$clusters_palette) +
scale_color_manual(values = timor.nutrients::palettes$clusters_palette) +
annotate(
'text',
x = 3.5,
y = 2.5,
label = 'On average, FNP-3 provides enough\ncalcium for 2.2 people per 1kg of catch,\nwhile FNP-1 and FNP-2 support\n0.4 and 0.6 people, respectively',
size = 2.75
) +
#annotate(
# 'rect',
# xmin = 0,
# ymin = 0.5,
# ymax = 1.5,
# xmax = 4.5,
#alpha = 0.5,
# color = rgb(0, 0, 0, alpha = 0.85),
# linewidth = 0.3,
#fill = "transparent",
#linetype = 2
#) +
annotate(
'curve',
x = 3.4, # Play around with the coordinates until you're satisfied
y = 1.8,
yend = 1.3,
xend = 2.45,
col = 'black',
curvature = -0.05,
linewidth = 0.3,
arrow = arrow(length = unit(0.25, 'cm'))
)
plots <-
list(
plots2 + ggplot2::labs(subtitle = "Gill nets"),
plots1 + ggplot2::labs(subtitle = "Other gears")
)
legend_plot <- cowplot::get_legend(plots[[1]] +
ggplot2::theme(
legend.position = "right",
legend.key.size = ggplot2::unit(0.55, "cm"),
legend.title = ggplot2::element_text(size = 12)
))
combined_plots <- cowplot::plot_grid(plotlist = plots, ncol = 2, labels = "AUTO")
x_label <- cowplot::draw_label("NDS per 1kg of catch", x = 0.5, y = 0.05)
y_label <- cowplot::draw_label("Nutrient", x = 0.04, y = 0.5, angle = 90)
final_plot <-
cowplot::plot_grid(
combined_plots,
legend_plot,
ncol = 2,
rel_widths = c(1, 0.15),
scale = 0.9
) +
x_label +
y_label
final_plot
Code
kmean_plots <- data$kmeans_plots
plots <-
list(
kmean_plots$kmeans_timor_GN + ggplot2::labs(subtitle = "Gill nets"),
kmean_plots$kmeans_timor_AG + ggplot2::labs(subtitle = "Other gears")
)
plots <- lapply(plots, function(x) {
x +
ggpubr::theme_pubr()+
ggplot2::theme(
legend.position = "none",
plot.margin = unit(c(0, 0, 0, 0), "cm"),
panel.grid = ggplot2::element_blank()
) +
ggplot2::labs(
fill = "Profiles",
color = "Profiles"
)+
ggplot2::scale_color_manual(
values = timor.nutrients::palettes$clusters_palette,
labels = function(x) paste0("FNP-", x)
) +
ggplot2::scale_fill_manual(
values = timor.nutrients::palettes$clusters_palette,
labels = function(x) paste0("FNP-", x)
)
})
legend_plot <- cowplot::get_legend(plots[[1]] +
ggplot2::theme(
legend.position = "right",
legend.key.size = ggplot2::unit(0.6, "cm"),
legend.title = ggplot2::element_text(size = 12)
))
combined_plots <- cowplot::plot_grid(plotlist = plots, ncol = 2, labels = "AUTO")
# x_label <- cowplot::draw_label("False positive rate\n(1 - Specificity)", x = 0.5, y = 0.05)
# y_label <- cowplot::draw_label("True positive rate\n(Sensitivity)", x = 0.02, y = 0.5, angle = 90)
final_plot <-
cowplot::plot_grid(
combined_plots,
legend_plot,
ncol = 2,
rel_widths = c(1, 0.1),
scale = 0.9
)
final_plot
Code
timor.nutrients::perm_results %>%
dplyr::bind_rows(.id = "subset") %>%
dplyr::mutate(dplyr::across(c(SumOfSqs, R2, statistic), ~ round(.x, 2)),
p.value = ifelse(p.value <= 0.001, "< 0.001", p.value),
subset = stringr::str_remove(subset, "_perm"),
subset = stringr::str_replace(subset, "timor", "mainland")
) %>%
reactable::reactable(
theme = reactablefmtr::fivethirtyeight(centered = TRUE),
groupBy = "subset",
defaultExpanded = TRUE,
pagination = FALSE,
compact = FALSE,
borderless = FALSE,
striped = FALSE,
defaultColDef = reactable::colDef(
align = "center"
),
columns = list(
subset = reactable::colDef(
minWidth = 120
)
)
)
Code
models_auc <-
timor.nutrients::model_outputs %>%
purrr::map(purrr::pluck(8)) %>%
dplyr::bind_rows(.id = "subset") %>%
dplyr::select(-estimator) %>%
tidyr::pivot_wider(names_from = subset, values_from = estimate)
plots <-
list(
timor.nutrients::model_outputs$model_timor_GN$roc_curves + ggplot2::labs(subtitle = paste0("Gill nets", " (", models_auc$model_timor_GN, ")")),
timor.nutrients::model_outputs$model_timor_AG$roc_curves + ggplot2::labs(subtitle = paste0("Other gears", " (", models_auc$model_timor_AG, ")"))
)
plots <- lapply(plots, function(x) {
x +
ggpubr::theme_pubr()+
ggplot2::theme(
panel.grid = ggplot2::element_blank(),
legend.position = "none",
plot.margin = unit(c(0, 0, 0, -0.1), "cm")
) +
ggplot2::coord_cartesian(expand = T) +
ggplot2::labs(x = "", y = "", color = "Profiles")+
ggplot2::scale_color_manual(
values = timor.nutrients::palettes$clusters_palette,,
labels = function(x) paste0("FNP-", x)
) +
ggplot2::scale_fill_manual(
values = timor.nutrients::palettes$clusters_palette,,
labels = function(x) paste0("FNP-", x)
)
})
legend_plot <- cowplot::get_legend(plots[[1]] +
ggplot2::theme(
legend.position = "right",
legend.key.size = ggplot2::unit(0.8, "cm"),
legend.title = ggplot2::element_text(size = 12)
))
combined_plots <- cowplot::plot_grid(plotlist = plots, ncol = 2, labels = "AUTO", vjust = 0.2)
x_label <- cowplot::draw_label("False positive rate (1 - Specificity)", x = 0.5, y = 0.05)
y_label <- cowplot::draw_label("True positive rate (Sensitivity)", x = 0.02, y = 0.5, angle = 90)
final_plot <-
cowplot::plot_grid(
combined_plots,
legend_plot,
ncol = 2,
rel_widths = c(1, 0.15),
scale = 0.9
) +
x_label +
y_label
final_plot
Code
models_metrics <-
timor.nutrients::model_outputs %>%
purrr::map(purrr::pluck(4)) %>%
purrr::imap(~ summary(.x)) %>%
dplyr::bind_rows(.id = "subset") %>%
dplyr::select(-.estimator) %>%
tidyr::pivot_wider(names_from = subset, values_from = .estimate) %>%
dplyr::rename(metric = .metric) %>%
na.omit()
dplyr::bind_rows(models_auc, models_metrics) %>%
dplyr::rename(
"Other gears" = model_timor_AG,
"Gill nets" = model_timor_GN
) %>%
dplyr::mutate(dplyr::across(.cols = dplyr::where(is.numeric), ~ round(.x, 2))) %>%
reactable::reactable(
theme = reactablefmtr::fivethirtyeight(centered = TRUE),
defaultExpanded = TRUE,
pagination = FALSE,
compact = FALSE,
borderless = FALSE,
striped = FALSE,
defaultColDef = reactable::colDef(
align = "center"
),
columns = list(
metric = reactable::colDef(
minWidth = 120
)
)
)
Code
importance_ag <-
model_outputs$model_timor_AG$fit %>%
workflows::extract_fit_parsnip() %>%
vip::vi() %>%
dplyr::mutate(
category = dplyr::case_when(
stringr::str_detect(Variable, "gear_type") ~ "gear_type",
stringr::str_detect(Variable, "habitat_gear") ~ "habitat_gear",
stringr::str_detect(Variable, "habitat") ~ "habitat",
stringr::str_detect(Variable, "quarter") ~ "quarter",
stringr::str_detect(Variable, "vessel_type") ~ "vessel_type",
TRUE ~ "other"
)
) %>%
dplyr::group_by(category) %>%
dplyr::summarize(Aggregated_Importance = sum(Importance)) %>%
dplyr::arrange(dplyr::desc(Aggregated_Importance))
importance_gn <-
model_outputs$model_timor_GN$fit %>%
workflows::extract_fit_parsnip() %>%
vip::vi() %>%
dplyr::mutate(
category = dplyr::case_when(
stringr::str_detect(Variable, "mesh_size") ~ "mesh_size",
stringr::str_detect(Variable, "habitat_mesh") ~ "habitat_mesh",
stringr::str_detect(Variable, "habitat") ~ "habitat",
stringr::str_detect(Variable, "quarter") ~ "quarter",
stringr::str_detect(Variable, "vessel_type") ~ "vessel_type",
TRUE ~ "other"
)
) %>%
dplyr::group_by(category) %>%
dplyr::summarize(Aggregated_Importance = sum(Importance)) %>%
dplyr::arrange(dplyr::desc(Aggregated_Importance))
importance_plot <-
dplyr::bind_rows(
importance_ag %>% dplyr::mutate(model = "Other gears"),
importance_gn %>% dplyr::mutate(model = "Gill nets")
) %>%
dplyr::mutate(category = dplyr::case_when(category == "habitat_gear" ~ "habitat x gear type",
category == "habitat_mesh" ~ "habitat x mesh size",
TRUE ~ category),
category = stringr::str_replace(category, "_", " "),
category = stringr::str_to_title(category)
) %>%
ggplot(aes(x = reorder(category, Aggregated_Importance), y = Aggregated_Importance)) +
ggpubr::theme_pubr(border = TRUE) +
facet_wrap(~model, scales = "free") +
geom_col(width = 0.2, fill = "#1c8097", alpha = 0.75) +
coord_flip() +
labs(
x = "Predictor",
y = "Aggregated Feature Importance\n(XGBoost Gain)"
) +
theme(
panel.grid.major.y = element_line(linetype = "dashed"),
strip.background = ggplot2::element_blank(),
strip.text = element_text(size = 12),
axis.text.y = ggtext::element_markdown(size = 9),
panel.spacing = unit(0.1, "lines"),
)
cowplot::ggdraw(importance_plot) +
cowplot::draw_plot_label(
label = c("A", "B"),
x = c(0.02, 0.52), # Adjust the x position of labels
y = c(0.98, 0.98), # Adjust the y position of labels
size = 15
)
Code
sha_Mgn <- shapviz::shapviz(timor.nutrients::shap_results$model_timor_GN)
annotation_data <- data.frame(
profile = "FNP-3",
x = 0.175,
y = 120,
label = 'FNP-3 profile likelihood increases\nwith <40mm mesh in pelagic and\nmangrove areas, and 50.8mm mesh\nin reef and FAD zones'
)
p2 <-
sha_Mgn %>%
purrr::map(get_shaps, model_type = "gn") %>%
dplyr::bind_rows(.id = "profile") %>%
dplyr::mutate(profile = stringr::str_replace(profile, ".pred_", "FNP-")) %>%
dplyr::group_by(profile, habitat_fact, mesh_fact) %>%
dplyr::summarise(mesh_shap = median(mesh_shap, na.rm = TRUE)) %>%
dplyr::ungroup() %>%
dplyr::filter(mesh_shap > 0) %>%
dplyr::mutate(habitat_fact = dplyr::case_when(habitat_fact == "Deep" ~ "Pelagic", TRUE ~ habitat_fact)) %>%
ggplot2::ggplot(ggplot2::aes(mesh_shap, mesh_fact, color = habitat_fact)) +
facet_grid(. ~ factor(profile, levels = c("FNP-3", "FNP-1", "FNP-2")), scales = "free") +
ggplot2::geom_point(ggplot2::aes(alpha = sqrt(mesh_shap), size = mesh_shap)) +
ggpubr::theme_pubr(border = TRUE) +
ggplot2::scale_color_manual(values = c("#f28f3b", "#c27ba0", "#ffd5c2", "#588b8b", "#c8553d", "#2d3047", "#007ea7")) +
ggplot2::coord_cartesian(expand = TRUE) +
ggplot2::scale_y_reverse(n.breaks = 10) +
ggplot2::labs(color = "Habitat") +
ggplot2::theme(
panel.grid = ggplot2::element_blank(),
strip.background = ggplot2::element_blank(),
strip.text.x = ggplot2::element_text(face = "bold")
) +
ggplot2::guides(
color = ggplot2::guide_legend(override.aes = list(size = 3)),
alpha = "none",
size = "none"
) +
ggplot2::geom_text(
data = annotation_data,
aes(x = x, y = y, label = label),
size = 3,
fontface = "plain",
inherit.aes = FALSE
) +
ggplot2::geom_rect(
data = annotation_data,
aes(xmin = 0.27, xmax = 0.36, ymin = 19, ymax = 57),
fill = "white",
alpha = 0.2,
color = "black",
inherit.aes = FALSE,
linetype = "dashed"
) +
ggplot2::geom_curve(
data = annotation_data,
aes(x = 0.32, y = 60, xend = 0.29, yend = 90),
curvature = -0.1,
color = 'black',
linewidth = 0.4,
arrow = arrow(length = unit(0.4, 'cm')),
inherit.aes = FALSE
) +
ggplot2::labs(x = "", y = "")
leg <- cowplot::get_legend(p2 +
ggplot2::theme(
plot.margin = unit(c(2, 0, 0, 0.9), "cm"),
# legend.title = ggplot2::element_text(size = 11),
legend.position = "right",
legend.direction = "vertical",
legend.justification = "right",
legend.box.just = "right",
legend.background = element_rect(fill = "transparent", colour = NA),
legend.box.background = element_rect(fill = "transparent", colour = NA)
))
base_plot <-
cowplot::plot_grid(
p2 + theme(
legend.position = "none",
plot.margin = unit(c(-0.2, 0.5, 0, 0.9), "cm")
),
ncol = 1,
labels = c("A", "B"),
hjust = -3.5,
vjust = 1.2,
align = "v"
)
grid <-
cowplot::plot_grid(
base_plot,
nrow = 1
)
pp1 <-
cowplot::ggdraw() +
cowplot::draw_plot(grid) +
cowplot::draw_label("Mesh size (mm)", x = 0.03, y = 0.7, angle = 90, hjust = 1, size = 12)
sha_Mag <- shapviz::shapviz(timor.nutrients::shap_results$model_timor_AG)
process_shap <-
sha_Mag %>%
purrr::map(get_shaps, model_type = "ag") %>%
dplyr::bind_rows(.id = "profile") %>%
tidyr::separate(habitat_gear_fact, into = c("habitat", "gear_fact"), sep = "_") %>%
dplyr::mutate(
gear_fact = stringr::str_to_title(gear_fact),
profile = stringr::str_replace(profile, ".pred_", "FNP-"),
habitat_gear_fact = paste0(habitat, " x ", gear_fact),
habitat_gear_fact = stringr::str_replace(habitat_gear_fact, "Deep", "Pelagic")
)
to_group <-
process_shap %>%
dplyr::mutate(
zero_dist = 0 - abs(gear_fact_shap)
) %>%
dplyr::group_by(gear_fact) %>%
dplyr::summarise(zero_dist = mean(zero_dist)) %>%
dplyr::slice_max(order_by = zero_dist, n = 15) %>%
magrittr::extract2("gear_fact")
annotation_data <- data.frame(
profile = "FNP-2",
x = 0.171,
y = 5.3,
label = 'Long lines in pelagic, FADs\nand magroves areas boost chances\nof obtaining FNP-2 profile'
)
p2 <-
process_shap %>%
dplyr::mutate(gear_fact_shap = ifelse(gear_fact_shap %in% to_group, "Others", gear_fact_shap)) %>%
dplyr::group_by(profile, gear_fact, habitat_fact) %>%
dplyr::summarise(gear_fact_shap = median(gear_fact_shap, na.rm = TRUE)) %>%
dplyr::ungroup() %>%
dplyr::filter(gear_fact_shap > 0) %>%
dplyr::mutate(habitat_fact = dplyr::case_when(habitat_fact == "Deep" ~ "Pelagic", TRUE ~ habitat_fact)) %>%
ggplot2::ggplot(ggplot2::aes(gear_fact_shap, gear_fact, color = habitat_fact)) +
facet_grid(. ~ profile, scales = "free") +
ggplot2::geom_point(ggplot2::aes(alpha = sqrt(gear_fact_shap), size = gear_fact_shap)) +
ggpubr::theme_pubr(border = TRUE) +
ggplot2::scale_color_manual(values = c("#f28f3b", "#c27ba0", "#ffd5c2", "#588b8b", "#c8553d", "#2d3047", "#007ea7")) +
ggplot2::coord_cartesian(expand = TRUE) +
ggplot2::scale_x_continuous(n.breaks = 4) +
ggplot2::labs(color = "Habitat") +
ggplot2::theme(
panel.grid = ggplot2::element_blank(),
strip.background = ggplot2::element_blank(),
strip.text.x = ggplot2::element_text(face = "bold")
) +
ggplot2::geom_text(
data = annotation_data,
aes(x = x, y = y, label = label),
size = 3,
fontface = "plain",
inherit.aes = FALSE
) +
ggplot2::geom_curve(
data = annotation_data,
aes(x = 0.174, y = 3, xend = 0.172, yend = 4.2),
curvature = -0.2,
color = 'black',
linewidth = 0.4,
arrow = arrow(length = unit(0.4, 'cm')),
inherit.aes = FALSE
) +
ggplot2::geom_rect(
data = annotation_data,
aes(xmin = 0.1745, xmax = 0.178, ymin = 2.5, ymax = 3.5),
fill = "white",
alpha = 0.2,
color = "black",
inherit.aes = FALSE,
linetype = "dashed"
) +
ggplot2::guides(
color = ggplot2::guide_legend(override.aes = list(size = 3)),
alpha = "none",
size = "none"
) +
ggplot2::labs(x = "", y = "")
leg <- cowplot::get_legend(p2 +
ggplot2::theme(
plot.margin = unit(c(2, 0, 0, 0.9), "cm"),
# legend.title = ggplot2::element_text(size = 11),
legend.position = "right",
legend.direction = "vertical",
legend.justification = "right",
legend.box.just = "right",
legend.background = element_rect(fill = "transparent", colour = NA),
legend.box.background = element_rect(fill = "transparent", colour = NA)
))
base_plot <-
cowplot::plot_grid(
p2 + theme(
legend.position = "none",
plot.margin = unit(c(-0.2, 0.5, 0, 0.9), "cm")
),
ncol = 1,
labels = c("B", "D"),
hjust = -3.5,
vjust = 1.2,
align = "v"
)
grid <-
cowplot::plot_grid(
base_plot,
nrow = 1
)
pp2 <-
cowplot::ggdraw(ylim = c(-.05, NA)) +
cowplot::draw_plot(grid) +
cowplot::draw_label("Gear type", x = 0.03, y = 0.7, angle = 90, hjust = 1, size = 12) +
cowplot::draw_label("Impact on model output (SHAP value)", x = 0.5, y = 0, size = 12)
# Extract the shared legend with larger text and key sizes
shared_legend <- cowplot::get_legend(
p2 +
ggplot2::theme(
legend.position = "right", # Position the legend on the right
legend.direction = "vertical", # Vertical orientation
legend.justification = "center",
legend.box.just = "center",
legend.text = ggplot2::element_text(size = 12), # Increase text size
legend.title = ggplot2::element_text(size = 14), # Increase title size
legend.key.size = unit(1.5, "lines"), # Increase legend key size
legend.background = ggplot2::element_rect(fill = "transparent", colour = NA),
legend.box.background = ggplot2::element_rect(fill = "transparent", colour = NA)
)
)
# Remove legends from individual plots
pp1_no_legend <-
pp1 +
ggplot2::theme(legend.position = "none")
pp2_no_legend <-
pp2 +
ggplot2::theme(legend.position = "none")
# Combine the two plots vertically without legends
plots_combined <- cowplot::plot_grid(
pp1_no_legend,
pp2_no_legend,
align = "v", # Align the plots vertically
ncol = 1, # Stack in one column
rel_heights = c(1, 1) # Adjust heights if necessary
)
# Add the shared legend to the right
final_plot <- cowplot::plot_grid(
plots_combined,
shared_legend,
ncol = 2, # Add legend to the right of the plots
rel_widths = c(3, 0.5) # Adjust widths for the plots and legend
)
# Display the final plot
print(final_plot)