Side by side interactive map with {leaflet} and {leaflet.extras2}

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

February 21, 2025


Understanding climate change requires robust models that simulate past, present, and future climate conditions. The Coupled Model Intercomparison Project (CMIP) plays a crucial role in this effort by providing a standardized framework for climate modeling worldwide.

CMIP is an international collaboration that brings together climate modeling centers to compare and analyze Earth System Models (ESMs). It is coordinated by the World Climate Research Programme (WCRP) and supports climate assessments such as the Intergovernmental Panel on Climate Change (IPCC) reports.

The project is organized into different phases (CMIP3, CMIP5, CMIP6), each improving model simulations and expanding research capabilities. These models help scientists explore climate variability, assess future climate projections, and study interactions between the atmosphere, oceans, and land.

One of the key advancements in CMIP6 is the use of Shared Socioeconomic Pathways (SSPs), which describe different possible futures based on socioeconomic developments and greenhouse gas (GHG) emissions. The SSPs are used in combination with Representative Concentration Pathways (RCPs) to explore climate impacts under various global conditions.

CMIP6 defines five SSPs, each representing a different trajectory of socioeconomic development and climate action:

  1. SSP1-1.9 & SSP1-2.6 (“Sustainability - Taking the Green Road”)
    • A world that prioritizes sustainable development, global cooperation, and low emissions.
    • Outcome: Rapid decarbonization, limiting warming to 1.5°C–2°C by 2100.
    • Example: Strong investments in green technologies, renewable energy, and social equity.
  2. SSP2-4.5 (“Middle of the Road”)
    • A business-as-usual scenario with moderate emissions and socio-economic development.
    • Outcome: Warming of 2.5°C–3°C by 2100.
    • Example: Some global efforts to reduce emissions, but no major breakthroughs.
  3. SSP3-7.0 (“Regional Rivalry - A Rocky Road”)
    • A fragmented world with regional conflicts, slow economic growth, and weak climate policies.
    • Outcome: High emissions, 3°C–4°C warming by 2100.
    • Example: Focus on national security, protectionist policies, and reliance on fossil fuels.
  4. SSP4-6.0 (“Inequality - A Divided World”)
    • A highly unequal world where technological progress benefits only some nations, leading to uneven climate mitigation.
    • Outcome: 2.5°C–3.5°C warming by 2100.
    • Example: Advanced economies transition to clean energy, while others remain fossil-fuel dependent.
  5. SSP5-8.5 (“Fossil-Fueled Development - Taking the Highway”)
    • A world driven by high economic growth and fossil fuel expansion, with little concern for climate policy.
    • Outcome: Extreme warming of 4°C–5°C by 2100.
    • Example: Strong technological advances, but continued reliance on coal, oil, and gas.

Why is CMIP Important?

  • Climate Projections: CMIP models simulate future climate scenarios under different greenhouse gas emission pathways.
  • Scientific Collaboration: It enables researchers to compare models, understand uncertainties, and improve forecasting methods.
  • Policy Support: CMIP outputs are widely used in climate risk assessments and policy decision-making at national and global levels.

The CMIP6 statistically downscaled climate dataset provides high-resolution climate projections for Canada based on the Coupled Model Intercomparison Project Phase 6 (CMIP6) models. The dataset includes temperature and precipitation data for the period 1950-2100 under different Shared Socioeconomic Pathways (SSPs) and can be found here.

Goal

The goal of this tutorial is to download, process, and visualize CMIP6 climate model data using R. We will:

  • Download CMIP6 downscaled data.
  • Process NetCDF files and convert them into spatial raster formats.
  • Create an interactive side-by-side map visualization.

By the end of this tutorial, you will be able to explore and visualize climate change data interactively in R. Let’s get started!

Get the data

Region borders

We need the polygon of the region of interest. We will use the rgeoboundaries package to extract the polygon of Quebec.

qc_sf <- rgeoboundaries::gb_adm2(country = "CAN") |>
    filter(shapeName %in% c("Bas-Saint-Laurent", 
                          "Gaspésie--Îles-de-la-Madelei", 
                          "Capitale-Nationale",
                          "Chaudière-Appalaches",
                          "Estrie",
                          "Centre-du-Québec",
                          "Montérégie",
                          "Montréal",
                          "Laval",
                          "Outaouais",
                          "Abitibi-Témiscamingue",
                          "Lanaudière",
                          "Laurentides",
                          "Mauricie")) |> 
  select(shapeName, geometry) |> 
  st_set_crs("WGS84") 
qc_sf #geographic coordinate
Simple feature collection with 14 features and 1 field
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: -79.58688 ymin: 44.99114 xmax: -61.14201 ymax: 49.25699
Geodetic CRS:  WGS 84
First 10 features:
                      shapeName                       geometry
1  Gaspésie--Îles-de-la-Madelei MULTIPOLYGON (((-66.32593 4...
2             Bas-Saint-Laurent MULTIPOLYGON (((-67.59801 4...
3            Capitale-Nationale MULTIPOLYGON (((-69.70949 4...
4          Chaudière-Appalaches MULTIPOLYGON (((-70.09711 4...
5                        Estrie MULTIPOLYGON (((-71.46412 4...
6              Centre-du-Québec MULTIPOLYGON (((-72.03755 4...
7                    Montérégie MULTIPOLYGON (((-72.3144 45...
8                      Montréal MULTIPOLYGON (((-73.47668 4...
9                         Laval MULTIPOLYGON (((-73.53145 4...
10                   Lanaudière MULTIPOLYGON (((-73.03963 4...
plot(qc_sf$geometry)

Temperature data

We will download the temperature data for Quebe from the CanDCS-M6 dataset. From the website, I selected the canDSC-M6 dataset for the ensemble mean temperature with the historical+SSP2-4.5 scenario.

Now let’s download the cnc files and convert them into raster format.

# Download the data
nc_files <- list.files("CanDCS-M6/", pattern = "\\.nc$", full.names = TRUE)
  
r <- rast(nc_files)

# Print metadata
print(r)

#Crop
r_ca<-r |> 
  terra::crop(
        qc_sf,
        snap = "in",
        mask = TRUE
    )

Krigging

In order to create an interesting visual, we need to disagregate the data. We will use the KrigR package to disaggregate the data.

2024

Let’s start with 2024.

library(KrigR)

Covsls <- CovariateSetup(
  Training = mean_temp_2024,
  Target = .009,
  Dir = Dir.Covariates,
  Keep_Global = TRUE
)

QuickStart_Krig <- Kriging(
  Data = mean_temp_2024, # data we want to krig as a raster object
  Covariates_training = Covsls[[1]], # training covariate as a raster object
  Covariates_target = Covsls[[2]], # target covariate as a raster object
  Equation = "GMTED2010", # the covariate(s) we want to use
  nmax = 40, # degree of localisation
  Cores = 3, # we want to krig using three cores to speed this process up
  FileName = "QuickStart_Krig", # the file name for our full kriging output
  Dir = Dir.Exports # which directory to save our final input in
)
temp2024<- terra::rast("Exports/QuickStart_Krig_Kriged.nc")

temp2024_crop <- temp2024 |>
    terra::crop(
        qc_sf,
        snap = "in",
        mask = TRUE
    )

writeRaster(temp2024_crop, "Data/temp2024_crop.tif", overwrite=TRUE)

2100

Now we will disaggregate the data for 2100.

library(KrigR)

Covsls <- CovariateSetup(
  Training = mean_temp_2100,
  Target = .009,
  Dir = Dir.Covariates,
  Keep_Global = TRUE
)

QuickStart_Krig <- Kriging(
  Data = mean_temp_2100, # data we want to krig as a raster object
  Covariates_training = Covsls[[1]], # training covariate as a raster object
  Covariates_target = Covsls[[2]], # target covariate as a raster object
  Equation = "GMTED2010", # the covariate(s) we want to use
  nmax = 40, # degree of localisation
  Cores = 3, # we want to krig using three cores to speed this process up
  FileName = "QuickStart_Krig", # the file name for our full kriging output
  Dir = Dir.Exports # which directory to save our final input in
)
#| eval: FALSE
temp2100<- terra::rast("Exports/QuickStart_Krig_Kriged.nc")

temp2100_crop <- temp2100 |>
    terra::crop(
        qc_sf,
        snap = "in",
        mask = TRUE
    )

writeRaster(temp2100_crop, "Data/temp2100_crop.tif", overwrite=TRUE)

Visualization

Now that we have the data, we can create an interactive side-by-side map visualization of the mean temperature for 2024 and 2100 for this region. We will use the leaflet and leaflet.extras2 packages to create the map.

library(leaflet)
library(leaflet.extras2)

r1 <- rast("Data/temp2024_crop.tif")
r2 <- rast("Data/temp2100_crop.tif")
  
pal <- colorNumeric("plasma", domain=c(0, 12), na.color = "transparent")

leaflet(width = "100%") |>
      addMapPane("right", zIndex = 1) |>
      addMapPane("left",  zIndex = 1) |>

      addTiles(urlTemplate = "https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png",
               group = "base", layerId = "baseid1", options = pathOptions(pane = "left"), "Mean Temperature (°C)") |>

      addTiles(urlTemplate = "https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png",
               group = "base", layerId = "baseid2", options = pathOptions(pane = "right"), "Mean Temperature (°C)") |>

      addRasterImage(x = r1, colors = pal, options = leafletOptions(pane = "left"), group = "2024") |>
      addRasterImage(x = r2, colors = pal, options = leafletOptions(pane = "right"), group = "2100") |>

      addSidebyside(layerId = "sidecontrols",
                    rightId = "baseid2",
                    leftId  = "baseid1")|>
      addLegend(pal = pal, 
                values = c(0, 12),
                title = "2024", 
                position = "bottomleft") |>
       addLegend(pal = pal, 
                 title = "2100", 
                 values=c(0, 12),
                 position = "bottomright") 

Conclusion

In this tutorial, we explored how to download, process, and visualize CMIP6 climate model data using R. We downloaded temperature data for Quebec from the CanDCS-M6 dataset, processed the NetCDF files, and converted them into spatial raster formats. We then used the KrigR package to disaggregate the data and create an interactive side-by-side map visualization of the mean temperature for 2024 and 2100 for Quebec. This visualization provides an engaging way to explore climate change data and understand the potential impacts of different climate scenarios.


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

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