Below is an intiial analysis of the DHW from the 2024 mass coral bleaching event on the Great Barrier Reef.
First, load the GBRMPA shp files for the Great Barrier Reef. For reproducibility the files are downloadable from Bozec et al 2022, and may differ from the official GBRMPA files available from the GBRMPA geoportal.
library(httr)
library(tidyverse)
library(janitor)
library(sf)
library(stars)
library(raster)
library(exactextractr)
library(tmap)
library(kableExtra)
library(reactable)
library(ggplot2)
library(terra)
library(tidyterra)
# write a function to get GBR shape file boundaries from eAtlas
get_gbr_shape <- function(crs="EPSG:20353", source="file"){
if (source=="url"){
#download from eAtlas
url <- "https://nextcloud.eatlas.org.au/s/xQ8neGxxCbgWGSd/download/TS_AIMS_NESP_Torres_Strait_Features_V1b_with_GBR_Features.zip"
destfile <- "TS_AIMS_NESP_Torres_Strait_Features_V1b_with_GBR_Features.zip"
GET(url, write_disk(destfile, overwrite = TRUE))
if (!dir.exists("unzipped_files")) {
dir.create("unzipped_files")
}
unzip("TS_AIMS_NESP_Torres_Strait_Features_V1b_with_GBR_Features.zip", exdir = "unzipped_files")
shapefile_path <- "unzipped_files/TS_AIMS_NESP_Torres_Strait_Features_V1b_with_GBR_Features.shp"
gbr_shape <- st_read(shapefile_path, quiet=TRUE) %>%
mutate(longitude = st_drop_geometry(.)$X_COORD,
latitude = st_drop_geometry(.)$Y_COORD) |>
filter(FEAT_NAME=="Reef") |>
st_set_crs(4283) |>
st_transform(20353) |>
st_make_valid() |>
clean_names() |>
dplyr::select(loc_name_s, qld_name, gbr_name, label_id, geometry, longitude, latitude) |>
mutate(gbr_name = as.factor(gbr_name)) |>
mutate(label_id = as.factor(label_id))
zones <- read.csv("/Users/rof011/GBR-coral-bleaching/data/gbr_zones.csv")
gbr_shape_output <- left_join(gbr_shape, zones, by="label_id")
return(gbr_shape)
} else if (source=="file"){
#read from disk
shapefile_path <- "/Users/rof011/GBR-coral-bleaching/data/Great_Barrier_Reef_Features.shp"
gbr_shape <- st_read(shapefile_path, quiet=TRUE) %>%
mutate(longitude = st_drop_geometry(.)$X_COORD,
latitude = st_drop_geometry(.)$Y_COORD) |>
filter(FEAT_NAME=="Reef") |>
st_set_crs(4283) |>
st_transform(20353) |>
st_make_valid() |>
clean_names() |>
dplyr::select(loc_name_s, qld_name, gbr_name, label_id, geometry, longitude, latitude,
area_ha) |>
mutate(gbr_name = as.factor(gbr_name)) |>
mutate(label_id = as.factor(label_id))
zones <- read.csv("/Users/rof011/GBR-coral-bleaching/data/gbr_zones.csv")
gbr_shape_output <- left_join(gbr_shape, zones, by="label_id")
return(gbr_shape)
}
}
### note that sf throws topology errors:
# Error in scan(text = lst[[length(lst)]], quiet = TRUE) :
# scan() expected 'a real', got 'TopologyException:'
# Error in (function (msg) :
# TopologyException: CoverageUnion cannot process incorrectly noded inputs.
gbr_shape <- get_gbr_shape(source="file") |>
mutate(id=sub("([a-zA-Z])$", "", label_id)) |> # drop multi-named sub-reef ID
group_by(gbr_name, id) |>
summarise() |>
st_make_valid()
# get distinct label_ID for each reef without sub-headings
# complex as some reefs (e.g. U/N) are catch-all "unknown reefs"
gbr_shape_label_ID <- get_gbr_shape() |>
as_tibble() |>
mutate(gbr_name=as.factor(gbr_name)) |>
mutate(id=sub("([a-zA-Z])$", "", label_id)) |>
dplyr::select(gbr_name, id) |>
distinct(gbr_name,id)
### this approach seems to give the same approx reef area as the raw data:
gbr_shape_raw <- get_gbr_shape()
# gbr_shape |> st_area() |> sum() # 28560112188 [m^2]
# gbr_shape_raw |> st_area() |> sum() # 28560118763 [m^2]
head(gbr_shape) |> kable("html") %>%
kable_styling("striped", font_size=11) %>%
scroll_box(width = "100%")
| gbr_name | id | geometry |
|---|---|---|
| (Big) Broadhurst Reef (No 1) | 18-100 | POLYGON ((1848551 7867941, … |
| (Big) Broadhurst Reef (No 2) | 18-100 | POLYGON ((1845249 7862813, … |
| (Big) Stevens Reef | 20-295 | POLYGON ((2094621 7653332, … |
| (Little) Broadhurst Reef | 18-106 | POLYGON ((1846710 7851185, … |
| (Little) Stevens Reef | 20-294 | POLYGON ((2085467 7656254, … |
| Abott Reef | 19-222 | POLYGON ((2119752 7720364, … |
There are 3724 reefs, with seperate polygons for each reef label
identifier (e.g. U/N Reef has 09-361a through to 09-361f). Individual
polygons per reef ID were merged with sf::union to form
multipolygons (see example for U/N 20-299 reef which has 9 separate
label_id components).
tmap_mode("plot")
a <- tm_shape(gbr_shape_raw |> filter(grepl("20-299", label_id))) +
tm_polygons("loc_name_s", legend.show=FALSE) +
tm_graticules() +
tm_layout(main.title="U/N Reef (20-299) ", main.title.position = "center", main.title.size = 1) +
tmap_options(max.categories = 57)
b <- tm_shape(gbr_shape |> filter(grepl("20-299", id))) +
tm_polygons("aquamarine4", alpha=0.2) +
tm_layout(main.title="U/N Reef (20-299) merged", main.title.position = "center", main.title.size = 1) +
tm_graticules()
tmap_arrange(a,b, ncol=2)

The NOAA Coral Reef Watch (CRW) daily global 5km satellite coral bleaching Degree Heating Week (DHW) is a metric that shows accumulated heat stress.
The data is available from 01/04/1984 to present day (with a ~2 day lag for processing). Data was extracted for cells within the GBR boundaries as determined by the boundary box (plus a 1km buffer) from the GBR shape file above. Daily DHW were extracted for all 38 years (1985-2023) between 1st January to 1st July, on the assumption that the maximum heatstress would have passed by Austral winter (01/07) in each year.
For each gridcell, the maximum DHW value per year (“yearly maximum DHW”, Van Hooidonk & Huber 2009) was extracted for each year (1986:2024). DHW for 2024 were extracted separately due to an incomplete timeseries at the time of analysis. The approaches to calculating DHW on the GBR differ among studies, for example:
Further analysis on the distribution/shape of DHW will inform how the 2024 event compares to previous in terms of thermal profiles, but for an initial analysis on DHW the simple approach here uses yearly maximum DHW.
Note: each year of data is ~480mb in size, so total download size is ~15gb and may take some time
gbr_shape_bbox <- gbr_shape |>
st_transform(4326) |>
st_bbox()
gbr_shape_bbox <- gbr_shape |>
st_transform(4326) |>
st_bbox() |>
st_as_sfc() |>
st_buffer(1) |>
st_bbox()
# custom function for DHW conversion to spatraster
# (there are better functions to download erdapp data e.g. rerddap::griddap but this works for spatraster conversion ofyearly maximum DHW per polygon)
get_dhw_gbr <- function(timestart, timeend, timeout = 60, crs = "EPSG:20353") {
gbr_dhw_url <- paste0(
"https://coastwatch.pfeg.noaa.gov/erddap/griddap/NOAA_DHW.csv?", "CRW_DHW", "%5B(", timestart,
"T12:00:00Z):1:(", timeend, "T12:00:00Z)%5D%5B(",
-24.86075, "):1:(", -10.27304, ")%5D%5B(",
141.9369, "):1:(", 153.2032,
")%5D"
)
temp_file <- tempfile(fileext = ".csv")
GET(url = gbr_dhw_url, write_disk(temp_file, overwrite = TRUE), timeout(timeout))
csvdata <- read.csv(temp_file, header = TRUE, skip = 1)
write_csv(csvdata, paste0("dhw_", start_date, "_raw.csv"))
print(paste0("Downloading ", start_date, " - ", end_date))
csvdata <- csvdata |>
dplyr::select(2, 3, 4) |>
dplyr::group_by(degrees_east, degrees_north) |>
summarise(dhw = max(Celsius.weeks))
gbr_dhw <- tidyterra::as_spatraster(csvdata, crs = "EPSG:4326") |> project("EPSG:20353")
return(gbr_dhw)
}
# Loop the function across years from 1981 to 2023
gbr_dhw_data <- list()
for (year in 1985:2023) {
start_date <- paste0(year, "-01-01") # Define start and end dates for the given year
end_date <- paste0(year, "-07-01")
dhw_data <- tryCatch(
{ # Fetch the DHW data for the GBR
get_dhw_gbr(start_date, end_date, timeout = 500)
},
error = function(e) { # Use tryCatch to handle errors or timeouts
message(paste("Error fetching data for year", year, ":", e$message))
NULL # Return NULL if there was an error
}
)
gbr_dhw_data[[as.character(year)]] <- dhw_data # Store the list using the year as the name
}
# Ammend 2024 data
for (year in 2024) {
start_date <- paste0(year, "-01-01") # Define start and end dates for the given year
end_date <- paste0(year, "-07-01")
dhw_data <- tryCatch(
{ # Fetch the DHW data for the GBR
get_dhw_gbr(start_date, end_date, timeout = 500)
},
error = function(e) { # Use tryCatch to handle errors or timeouts
message(paste("Error fetching data for year", year, ":", e$message))
NULL # Return NULL if there was an error
}
)
gbr_dhw_data[[as.character(year)]] <- dhw_data # Store the list using the year as the name
}
# function borrowed from FAMEFMR::saveSpatRasterList:
gbr_dhw_data_list <- rapply(gbr_dhw_data_list, f = terra::wrap, classes = "SpatRaster", how = "replace")
qs::qsave(gbr_dhw_data_list, "gbr_dhw_data.RData")
As DHW is automatically calculated each day in the NOAA dataset, the
years in max DHW refer to the year of bleaching (e.g. 2016 = cumulative
heatstress from the end of 2015 and the start of 2016). For each reef
multipolygon in the gbr_shape dataset, the mean yearly
maximum DHW in each year was calculated using an area-weighted approach.
exactextractr::exact_extract was used over
stars::st_extract, vect::extract, and
raster::extract due to performance
issues with
stars/terra/rast.
The exact_extract approach used below is conservative in
that for larger reef polygons (or multipolygons) the function calculates
the mean value of cells that intersect the polygon,
weighted by the fraction cell coverage (as opposed to taking the
max value across all underlying cells). Undefined (NA)
values are ignored when they occur in the value raster, and cause the
output to be NA when present in the weights (check these later in the
inshore reefs). Below is a summary of the output:
library(reactable)
gbr_shape_dhw_list <- qs::qread("/Users/rof011/GBR-coral-bleaching/data/gbr_dhw_data.RData")
gbr_shape_dhw_list <- lapply(gbr_shape_dhw_list, function(x) terra::unwrap(x))
gbr_shape_dhw_list <- terra::rast(gbr_shape_dhw_list)
names(gbr_shape_dhw_list) <- paste0("year_", seq(1986, 2024, 1))
year_list <- paste0("year_", seq(1986, 2024, 1))
gbr_shape_dhw <- gbr_shape
for (i in year_list) {
year_col_name <- paste("dhw_max", sub("^.*_", "", i), sep = "_")
gbr_shape_dhw[[year_col_name]] <- exact_extract(gbr_shape_dhw_list[[i]],
progress = FALSE,
gbr_shape_dhw, fun = "mean", weights = "area"
)
}
head(gbr_shape_dhw) |>
kable("html") |>
kable_styling("striped", font_size = 11) |>
scroll_box(width = "100%")
| gbr_name | id | geometry | dhw_max_1986 | dhw_max_1987 | dhw_max_1988 | dhw_max_1989 | dhw_max_1990 | dhw_max_1991 | dhw_max_1992 | dhw_max_1993 | dhw_max_1994 | dhw_max_1995 | dhw_max_1996 | dhw_max_1997 | dhw_max_1998 | dhw_max_1999 | dhw_max_2000 | dhw_max_2001 | dhw_max_2002 | dhw_max_2003 | dhw_max_2004 | dhw_max_2005 | dhw_max_2006 | dhw_max_2007 | dhw_max_2008 | dhw_max_2009 | dhw_max_2010 | dhw_max_2011 | dhw_max_2012 | dhw_max_2013 | dhw_max_2014 | dhw_max_2015 | dhw_max_2016 | dhw_max_2017 | dhw_max_2018 | dhw_max_2019 | dhw_max_2020 | dhw_max_2021 | dhw_max_2022 | dhw_max_2023 | dhw_max_2024 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| (Big) Broadhurst Reef (No 1) | 18-100 | POLYGON ((1848551 7867941, … | 0.4779795 | 6.827402 | 0.000000 | 0.1597545 | 0.7435788 | 0.0000000 | 0.000000 | 0 | 1.7756083 | 1.6970549 | 0.4418001 | 0 | 0.3921288 | 0.4099048 | 0 | 0.6378967 | 2.2812221 | 0 | 2.099609 | 0.6406564 | 0.0000000 | 0 | 0.0000000 | 0.0086903 | 0.6626197 | 0.2797973 | 0.8909236 | 0.9841175 | 0 | 1.9966893 | 2.639892 | 3.855308 | 0.0000000 | 0 | 4.845179 | 0 | 5.318794 | 1.0536289 | 3.319114 |
| (Big) Broadhurst Reef (No 2) | 18-100 | POLYGON ((1845249 7862813, … | 0.4809034 | 6.690235 | 0.000000 | 0.1626551 | 0.7322140 | 0.0000000 | 0.000000 | 0 | 1.8063999 | 1.7350723 | 0.3083107 | 0 | 0.2800516 | 0.4745746 | 0 | 0.5255354 | 1.9665437 | 0 | 2.207775 | 0.5768712 | 0.0000000 | 0 | 0.0000000 | 0.0397638 | 0.6499974 | 0.5694084 | 0.9334313 | 1.0662649 | 0 | 1.9251226 | 2.608260 | 3.985060 | 0.0000000 | 0 | 4.911906 | 0 | 5.216156 | 1.0033153 | 3.714746 |
| (Big) Stevens Reef | 20-295 | POLYGON ((2094621 7653332, … | 2.2126808 | 7.462231 | 0.000000 | 0.0000000 | 0.6870964 | 0.3540293 | 1.372475 | 0 | 0.0930394 | 1.1178683 | 0.0926058 | 0 | 1.7353671 | 0.1865064 | 0 | 0.0013572 | 7.0890689 | 0 | 4.832458 | 0.2291969 | 1.4887915 | 0 | 0.6001107 | 0.8347213 | 2.2275841 | 0.0000000 | 0.7364363 | 0.6408299 | 0 | 1.2891974 | 1.597199 | 4.002799 | 0.0894790 | 0 | 8.630629 | 0 | 5.692474 | 0.8342787 | 8.230654 |
| (Little) Broadhurst Reef | 18-106 | POLYGON ((1846710 7851185, … | 0.4927949 | 7.060939 | 0.000000 | 0.1851825 | 0.7358017 | 0.0000000 | 0.000000 | 0 | 1.7554580 | 1.9170403 | 0.6352469 | 0 | 1.0039911 | 0.5008817 | 0 | 0.5964878 | 2.9083798 | 0 | 2.061579 | 1.0029445 | 0.0133093 | 0 | 0.0000000 | 0.0000000 | 0.7555013 | 0.2112552 | 0.8949642 | 1.1583098 | 0 | 2.1319892 | 2.261860 | 4.152460 | 0.0000000 | 0 | 4.817797 | 0 | 5.554096 | 1.2604388 | 3.465622 |
| (Little) Stevens Reef | 20-294 | POLYGON ((2085467 7656254, … | 2.1869435 | 7.334218 | 0.000000 | 0.0000000 | 0.7461356 | 0.6261856 | 1.198692 | 0 | 0.0085639 | 0.9957811 | 0.1803312 | 0 | 1.9897678 | 0.2502062 | 0 | 0.0000000 | 6.7362270 | 0 | 4.782020 | 0.3121046 | 1.6231992 | 0 | 0.4489488 | 0.9118187 | 2.2421041 | 0.0000000 | 0.8632997 | 0.6447247 | 0 | 1.2262332 | 1.900885 | 3.752129 | 0.1179417 | 0 | 9.029800 | 0 | 6.001618 | 1.0063132 | 8.097749 |
| Abott Reef | 19-222 | POLYGON ((2119752 7720364, … | 0.7593529 | 5.319762 | 0.594146 | 0.1600000 | 0.3113776 | 0.0000000 | 0.000000 | 0 | 0.1686566 | 0.7345553 | 0.1500000 | 0 | 1.1293507 | 0.0000000 | 0 | 1.1302553 | 0.9077468 | 0 | 3.292808 | 0.1700677 | 0.4479577 | 0 | 0.3000000 | 2.9156933 | 0.7369853 | 0.4514952 | 0.4714453 | 0.0000000 | 0 | 0.4719019 | 2.083957 | 2.504015 | 0.0000000 | 0 | 4.460752 | 0 | 4.484212 | 0.6828330 | 9.708863 |
saveRDS(gbr_shape_dhw, "/Users/rof011/GBR-coral-bleaching/data/gbr_shape_dhw.RDS")
As the dataset is in sf format, the output for each year
can be plotted spatially to compare the maximum DHW for adjacent reefs,
for example Heron Reef and Lizard Reef (Lizard Reef is composed of
multiple polygons based on label_ID) where the within-reef trajectories
are fit with a simple GAM model:
tmap_mode("plot")
a <- tm_shape(gbr_shape_dhw |> filter(grepl("Lizard", gbr_name)) |>
mutate(dhw_max_2016 = as.numeric(dhw_max_2016))) +
tm_polygons(col = "dhw_max_2016", palette = "-RdBu", breaks = seq(1:10), alpha = 0.8, legend.show = FALSE) +
tm_layout(main.title = "Lizard Island (2016)", main.title.position = "center", main.title.size = 1) +
tm_graticules(lwd = 0.2)
b <- tm_shape(gbr_shape_dhw |> filter(gbr_name == "Heron Reef") |>
mutate(dhw_max_2016 = as.numeric(dhw_max_2016))) +
tm_polygons(col = "dhw_max_2016", title = "yearly maximum DHW (2016)",
palette = "-RdBu", breaks = seq(1:10), alpha = 0.8) +
tm_layout(main.title = "Heron Reef (2016)", main.title.position = "center", main.title.size = 1) +
tm_graticules(lwd = 0.2)
tmap_arrange(b, a, ncol = 2)

The resulting yearly maximum DHW dataset can also be filtered as a time-series to quantify the trajectories of individual reefs through time for example Heron Island in the southern GBR and Lizard Island in the northern GBR (note RdBu used over NOAA palette as it’s confusing for interspaced polygons):
dhw_subset <- gbr_shape_dhw |>
filter(gbr_name=="Lizard Island Reef (North East)" | gbr_name=="Heron Reef") |>
as.data.frame() |>
dplyr::select(-id, -geometry) |>
pivot_longer(-gbr_name, names_to="year", values_to="dhw") |>
mutate(year = as.numeric(str_extract_all(year, "\\d+"))) |>
arrange(gbr_name, year)
ggplot() + theme_bw() + facet_wrap(~gbr_name, ncol=2) +
geom_smooth(data=dhw_subset, aes(x=year, y=dhw, color=gbr_name),
method = "gam", formula = y ~ s(x, bs = "cr", k = 10), show.legend = FALSE) +
geom_line(data=dhw_subset, aes(x=year, y=dhw, color=gbr_name), show.legend=FALSE) +
geom_point(data=dhw_subset, aes(year, dhw, fill=gbr_name), shape=21, size=2, show.legend=FALSE) +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1)) +
scale_fill_manual(values=c("aquamarine2", "coral2")) +
scale_color_manual(values=c("aquamarine4", "coral4"))

To check the numbers are correct, redownload the cells adjacent to Lizard Island and reprocess to get annual DHW pattern from 1986-2015 from surrounding gridcells. Max DHW closely matches the area-weighted calculations above.
library(rerddap)
library(lubridate)
#
# lizard_ts_DHW <- rerddap::griddap(
# dataset="NOAA_DHW",
# time = c('1995-01-01','2024-04-01'),
# latitude = c(-14.70627, -14.64135),
# longitude = c(145.43233, 145.47928),
# fields = c("CRW_DHW","CRW_SST","CRW_SSTANOMALY"),
# stride = 1,
# fmt = "csv")
#
# lizard_ts_DHW_2 <- rerddap::griddap(
# dataset="NOAA_DHW",
# time = c('1986-01-01','1995-04-01'),
# latitude = c(-14.70627, -14.64135),
# longitude = c(145.43233, 145.47928),
# fields = c("CRW_DHW","CRW_SST","CRW_SSTANOMALY"),
# stride = 1,
# fmt = "csv")
#
# lizard_DHW <- rbind(lizard_ts_DHW_2, lizard_ts_DHW)
# write.csv(lizard_DHW, "data/lizard_DHW.csv")
dhw_subset_lizard <- dhw_subset |>
filter(!gbr_name=="Heron Reef") |>
mutate(year = as.character(year),
time = paste0(year, "-03-01T12:00:00Z")) |>
mutate(time=ymd_hms(time)) |>
rename(crw_dhw=dhw)
lizard_DHW <- read.csv("/Users/rof011/GBR-coral-bleaching/data/lizard_DHW.csv")
lizard_DHW |>
mutate(time=ymd_hms(time)) |>
mutate(year= year(time)) |>
mutate(month=month(time)) |>
group_by(time) |>
summarise(crw_dhw=mean(crw_dhw), crw_sst=max(crw_sst)) |>
ggplot() + theme_bw() +
geom_line(aes(time, crw_dhw)) +
# geom_area(aes(time, crw_dhw), fill="darkred") +
scale_x_datetime(date_breaks = "1 year", date_labels = "%Y") +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_y_continuous(limits=c(0,10), breaks=seq(0,10,2)) +
ylab("Degree Heating Weeks")+ xlab("Year") +
geom_point(data=dhw_subset_lizard, aes(time, crw_dhw, fill=crw_dhw), stroke=0.5, size=3, shape=21) +
scale_fill_distiller(palette = "Reds", direction = 1, limits=c(0,10))

and between-cell variance explains the difference between means:
lizard_DHW |>
mutate(time=ymd_hms(time)) |>
mutate(year= year(time)) |>
mutate(month=month(time)) |>
mutate(cell=paste0("(",longitude," / ",latitude,")")) |>
mutate(cell=as.factor(cell)) |>
ggplot() + theme_bw() +
geom_line(aes(time, crw_dhw, color=cell)) +
scale_x_datetime(date_breaks = "1 year", date_labels = "%Y") +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_y_continuous(limits=c(0,10), breaks=seq(0,10,2)) +
ylab("Degree Heating Weeks")+ xlab("Year") +
scale_color_viridis_d(direction=-1, option="C") +
geom_point(data=dhw_subset_lizard, aes(time, crw_dhw, fill=crw_dhw), stroke=0.5, size=3, shape=21) +
scale_fill_distiller(palette = "Reds", direction = 1, limits=c(0,10))

finally plot spatial maps for max DHW per year showing the area-weighted vs cell-weighted approach:
# spatial
lizard_spat <- lizard_DHW |>
mutate(time=ymd_hms(time)) |>
mutate(year= year(time)) |>
group_by(year, longitude, latitude) |>
summarise(crw_dhw=max(crw_dhw)) |>
pivot_wider(names_from="year", values_from="crw_dhw") |>
tidyterra::as_spatraster(crs="EPSG:4326", xycols = 1:2) |> project("EPSG:20353")
gbr_shape_dhw <- readRDS("/Users/rof011/GBR-coral-bleaching/data/gbr_shape_dhw.RDS")
lizard_shape_dhw_map <- gbr_shape_dhw %>%
st_transform(20353) |>
mutate(across(where(is.numeric), round, digits = 1)) |>
filter(grepl("Lizard", gbr_name))
tmpthme <- theme(
axis.title.y = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1),
plot.title = element_text(size = 10)
)
p1998 <- ggplot() +
theme_bw() +
tidyterra::geom_spatraster(data = lizard_spat, aes(fill = 1998), show.legend = FALSE) +
scale_fill_viridis_c(option = "C", limits = c(0, 10)) +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1)) +
geom_sf(data = lizard_shape_dhw_map, alpha=0.6) + ggtitle("1998") +
theme(plot.title = element_text(size = 10))
p2002 <- ggplot() +
theme_bw() +
tidyterra::geom_spatraster(data = lizard_spat, aes(fill = 2002), show.legend = FALSE) +
tmpthme +
scale_fill_viridis_c(option = "C", limits = c(0, 10)) +
geom_sf(data = lizard_shape_dhw_map, alpha=0.6) + ggtitle("2002")
p2012 <- ggplot() +
theme_bw() +
tidyterra::geom_spatraster(data = lizard_spat, aes(fill = 2012), show.legend = FALSE) +
tmpthme +
scale_fill_viridis_c(option = "C", limits = c(0, 10)) +
geom_sf(data = lizard_shape_dhw_map, alpha=0.6) + ggtitle("2012")
p2016 <- ggplot() +
theme_bw() +
tidyterra::geom_spatraster(data = lizard_spat, aes(fill = 2016), show.legend = FALSE) +
tmpthme +
scale_fill_viridis_c(option = "C", limits = c(0, 10)) +
geom_sf(data = lizard_shape_dhw_map, alpha=0.6) + ggtitle("2016")
p2017 <- ggplot() +
theme_bw() +
tidyterra::geom_spatraster(data = lizard_spat, aes(fill = 2017), show.legend = FALSE) +
tmpthme +
scale_fill_viridis_c(option = "C", limits = c(0, 10)) +
geom_sf(data = lizard_shape_dhw_map, alpha=0.6) + ggtitle("2017")
p2020 <- ggplot() +
theme_bw() +
tidyterra::geom_spatraster(data = lizard_spat, aes(fill = 2020), show.legend = FALSE) +
tmpthme +
scale_fill_viridis_c(option = "C", limits = c(0, 10)) +
geom_sf(data = lizard_shape_dhw_map, alpha=0.6) + ggtitle("2020")
p2022 <- ggplot() +
theme_bw() +
tidyterra::geom_spatraster(data = lizard_spat, aes(fill = 2022), show.legend = FALSE) +
tmpthme +
scale_fill_viridis_c(option = "C", limits = c(0, 10)) +
geom_sf(data = lizard_shape_dhw_map, alpha=0.6) + ggtitle("2022")
p2024 <- ggplot() +
theme_bw() +
tidyterra::geom_spatraster(data = lizard_spat, aes(fill = 2024), show.legend = TRUE) +
tmpthme +
scale_fill_viridis_c(option = "C", limits = c(0, 10)) +
geom_sf(data = lizard_shape_dhw_map, alpha=0.6) + ggtitle("2024") +
guides(fill=guide_legend(title="maxDHW"))
p1998 | p2002 | p2012 | p2016 | p2017 | p2020 | p2022 | p2024
