Heatmap to Visualize Spatio-Temporal Data

By Johanie Fournier, agr., M.Sc. in rstats tidymodels tidytuesday eda viz

February 25, 2025

Vegetative period is the period of the year when plants grow and develop. The vegetative period is an essential factor in agriculture, as it determines the length of the growing season and the timing of planting and harvesting. The vegetative period is influenced by various factors, including temperature, precipitation, and day length. In this post, we will create a heatmap to visualize the spatio-temporal evolution of the vegetative period in the Chaudière-Appalaches region of Quebec over the past 20 years.

Goal

  • temperature data to calculate the vegetative period with the vegperiod package
  • create a heatmap to visualize the average vegetative period for each year over the past 20 years with ggplot2

Get the data

Region borders

We need the polygon of the region of interest. Données Québec provides a shapefile of the administrative regions of Quebec.

qc_sf <- read_sf("SHP/mrc_s.shp") |> 
  filter(MRS_NM_REG=="Chaudière-Appalaches") |> 
  select(MRS_NM_MRC, geometry)
plot(qc_sf$geometry)

Temperature data

We will extract temperature data from the AgERA5 dataset using the KrigR package. The AgERA5 dataset provides high-resolution climate data, including precipitation, temperature, and wind speed, for global climate research.

# Load the KrigR package
#api_user <- "*******************************" # PLEASE INSERT YOUR USER NUMBER
#api_key <- "********************************" # PLEASE INSERT YOUR API TOKEN

# List of available dataset
KrigR::Meta.List()

# Dataset description
KrigR::Meta.QuickFacts(
    "reanalysis-era5-land"
)
#extract precipitation data
start_date <- "2003-01-01 00:00"
end_date <- "2023-12-31 24:00"

temperature_raw <- KrigR::CDownloadS(
    Variable = "2m_temperature",
    DataSet = "reanalysis-era5-land",
    DateStart = start_date,
    DateStop = end_date,
    TResolution = "day",
    TZone = "CET",
    TStep = 1,
    Dir = Dir.Data,
    FileName = "temperature_raw",
    Extent = as(qc_sf, "Spatial"),
    API_User = api_user,
    API_Key = api_key,
    closeConnections = TRUE)

Data preperation

We will convert the raster data to a dataframe and extract the temperature values for the region of interest.

# Change layer names
day_vector <- seq(
    from = as.Date(start_date)-1,
    to = as.Date(end_date),
    by = "day"
)
names(temperature_raw) <- day_vector

# Raster to dataframe
temperature_sf <- temperature_raw |> 
  as.data.frame(
    precipitation_raw,
    xy = TRUE, na.rm = TRUE)|>
    tidyr::pivot_longer(
        !c(x, y),
        names_to = "date",
        values_to = "value"
    ) |> 
  mutate(year=year(date), 
         month=month(date),
         value=value-273.15) |> 
  select(x, y, date, year, month, value) |> 
  st_as_sf(coords=c("x", "y")) |> 
  st_set_crs("WGS84") |> 
  st_intersection(qc_sf)

Next, we need to calculate the vegetative period for each year in the region of interest. The vegetative period is the period of the year when plants grow and develop. We will use the vegperiod function from the vegperiod package to calculate the vegetative period based on the temperature data.

#All dayly data
temp_dt<-temperature_sf |> 
  as_tibble() |> 
  mutate(lon = st_coordinates(geometry)[,1],
         lat = st_coordinates(geometry)[,2]) |>
  select(-geometry) |> 
  mutate(date=as.Date(date)) |> 
  filter(date>="2003-01-01", date<="2023-12-31")

# Growing season length
library(vegperiod)

vegperiod_dt<-temp_dt |>
  group_by(MRS_NM_MRC) |>
  reframe(vegperiod=vegperiod(
    dates=date, 
    Tavg=value, 
    start.method="StdMeteo", 
    end.method="StdMeteo"
  )) |> 
  unnest(cols = c(vegperiod)) |> 
  mutate(vege_period=end-start) |> 
  select(MRS_NM_MRC, year, vege_period)

Heatmap

We will create a heatmap to visualize the spatio-temporal evolution of vegetative period in the Chaudière-Appalaches region. The heatmap will show the average vegetative period for each year over the past 20 years.

library(hrbrthemes)

gg<-ggplot(vegperiod_dt, aes(year, MRS_NM_MRC, fill= vege_period)) + 
  geom_tile() +
  scale_fill_distiller(palette = "RdYlBu") +
  theme_ipsum() +
  scale_x_continuous(breaks=seq(2003,2023,2), limits = c(2002.5, 2023.5))+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))+
  theme(axis.title.x = element_blank(), axis.title.y = element_blank())+
  labs(title = "Vegetative Period in Chaudière-Appalaches",
       fill = "Days")+
  theme(legend.position = "right")
gg

Conclusion

The heatmap shows the spatio-temporal evolution of the vegetative period in the Chaudières-Appalaches region over the past 20 years. The vegetative period is the period of the year when plants grow and develop. The heatmap shows that the vegetative period has been increasing over the past 20 years, which could be due to climate change. The heatmap provides valuable information for farmers and policymakers to make informed decisions about agriculture and land use in the region.


WANT MORE?

Sign up for exclusive content, emails & things I doesn't share anywhere else.

We respect your email privacy

Powered by AWeber Email Marketing

 

Session Info

sessionInfo()
R version 4.4.2 (2024-10-31)
Platform: aarch64-apple-darwin20
Running under: macOS Sequoia 15.3.1

Matrix products: default
BLAS:   /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRblas.0.dylib 
LAPACK: /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRlapack.dylib;  LAPACK version 3.12.0

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

time zone: America/Toronto
tzcode source: internal

attached base packages:
[1] stats     graphics  grDevices datasets  utils     methods   base     

other attached packages:
 [1] reticulate_1.40.0    jofou.lib_0.0.0.9000 tidytuesdayR_1.1.2  
 [4] tictoc_1.2.1         KrigR_0.9.4          ncdf4_1.23          
 [7] ecmwfr_2.0.2         rgeoboundaries_1.3.1 terra_1.8-10        
[10] sf_1.0-19            pins_1.4.0           fs_1.6.5            
[13] timetk_2.9.0         yardstick_1.3.2      workflowsets_1.1.0  
[16] workflows_1.1.4      tune_1.2.1           rsample_1.2.1       
[19] parsnip_1.2.1        modeldata_1.4.0      infer_1.0.7         
[22] dials_1.3.0          scales_1.3.0         broom_1.0.7         
[25] tidymodels_1.2.0     recipes_1.1.0        doFuture_1.0.1      
[28] future_1.34.0        foreach_1.5.2        skimr_2.1.5         
[31] gganimate_1.0.9      forcats_1.0.0        stringr_1.5.1       
[34] dplyr_1.1.4          purrr_1.0.2          readr_2.1.5         
[37] tidyr_1.3.1          tibble_3.2.1         ggplot2_3.5.1       
[40] tidyverse_2.0.0      lubridate_1.9.4      kableExtra_1.4.0    
[43] inspectdf_0.0.12.1   openxlsx_4.2.7.1     knitr_1.49          

loaded via a namespace (and not attached):
  [1] rstudioapi_0.17.1   jsonlite_1.8.9      magrittr_2.0.3     
  [4] magick_2.8.5        farver_2.1.2        rmarkdown_2.29     
  [7] vctrs_0.6.5         memoise_2.0.1       hoardr_0.5.5       
 [10] base64enc_0.1-3     htmltools_0.5.8.1   progress_1.2.3     
 [13] curl_6.1.0          parallelly_1.41.0   KernSmooth_2.23-26 
 [16] plyr_1.8.9          zoo_1.8-12          stars_0.6-7        
 [19] cachem_1.1.0        ggfittext_0.10.2    lifecycle_1.0.4    
 [22] iterators_1.0.14    pkgconfig_2.0.3     Matrix_1.7-2       
 [25] R6_2.5.1            fastmap_1.2.0       digest_0.6.37      
 [28] reshape_0.8.9       colorspace_2.1-1    furrr_0.3.1        
 [31] timechange_0.3.0    httr_1.4.7          abind_1.4-8        
 [34] compiler_4.4.2      intervals_0.15.5    proxy_0.4-27       
 [37] withr_3.0.2         backports_1.5.0     viridis_0.6.5      
 [40] DBI_1.2.3           MASS_7.3-64         lava_1.8.1         
 [43] rappdirs_0.3.3      classInt_0.4-11     tools_4.4.2        
 [46] units_0.8-5         zip_2.3.1           future.apply_1.11.3
 [49] nnet_7.3-20         glue_1.8.0          grid_4.4.2         
 [52] snow_0.4-4          generics_0.1.3      gtable_0.3.6       
 [55] countrycode_1.6.0   tzdb_0.4.0          class_7.3-23       
 [58] data.table_1.16.4   hms_1.1.3           sp_2.1-4           
 [61] xml2_1.3.6          pillar_1.10.1       splines_4.4.2      
 [64] lhs_1.2.0           tweenr_2.0.3        lattice_0.22-6     
 [67] FNN_1.1.4.1         renv_1.0.7          survival_3.8-3     
 [70] tidyselect_1.2.1    pbapply_1.7-2       gridExtra_2.3      
 [73] svglite_2.1.3       crul_1.5.0          xfun_0.50          
 [76] hardhat_1.4.0       timeDate_4041.110   stringi_1.8.4      
 [79] DiceDesign_1.10     yaml_2.3.10         evaluate_1.0.3     
 [82] codetools_0.2-20    httpcode_0.3.0      automap_1.1-12     
 [85] cli_3.6.3           rpart_4.1.24        systemfonts_1.2.1  
 [88] repr_1.1.7          munsell_0.5.1       spacetime_1.3-2    
 [91] Rcpp_1.0.14         doSNOW_1.0.20       globals_0.16.3     
 [94] png_0.1-8           parallel_4.4.2      gower_1.0.2        
 [97] prettyunits_1.2.0   GPfit_1.0-8         listenv_0.9.1      
[100] viridisLite_0.4.2   ipred_0.9-15        xts_0.14.1         
[103] prodlim_2024.06.25  e1071_1.7-16        gstat_2.1-2        
[106] crayon_1.5.3        rlang_1.1.5         cowplot_1.1.3      
Posted on:
February 25, 2025
Length:
7 minute read, 1391 words
Categories:
rstats tidymodels tidytuesday eda viz
Tags:
eda rstats tidymodels tidytuesday viz
See Also:
Side by side interactive map with {leaflet} and {leaflet.extras2}
Using {pollen} and {vegperiod} to analyze temperature, GDD, and vegetation period
Aminated Visualisation for Centre-du-Québec’s Precipitation