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:
- 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.
- 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.
- 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.
- 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.
- 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.
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