30 Years of Precipitation for Centre-du-Québec: Trends, Patterns & Anomalies
By Johanie Fournier, agr., M.Sc. in rstats tidymodels tidytuesday eda viz
January 29, 2025
Precipitation plays a crucial role in Quebec’s climate, influencing everything from agriculture to hydrology and urban planning. Understanding long-term rainfall patterns is essential for assessing climate variability, detecting anomalies, and making informed environmental decisions.
Building on my previous series exploring precipitation patterns across the St. Lawrence Lowlands, this post shifts focus to a much smaller scale, allowing for a more in-depth analysis. By examining 30 years of high-resolution precipitation data from the AgERA5 dataset for a single region —Centre-du-Québec— I aim to uncover localized trends, seasonal variations, and anomalies that might be overlooked in broader regional studies.
This detailed approach provides valuable insights into long-term precipitation dynamics, which are essential for climate research, agriculture, and water resource management.
Goal
In this study, I aim to:
- Explore Long-Term Trends – Identify how precipitation patterns have evolved over the past 30 years, detecting any significant increases, decreases, or shifts.
- Analyze Seasonal Variations – Examine how precipitation levels fluctuate throughout the year and determine whether seasonality has changed over time.
- Detect Anomalies & Extreme Events – Identify unusual precipitation events, such as extreme rainfall periods or prolonged dry spells, and assess their frequency and intensity.
Get the data
Municipality 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("Centre-du-Québec")) |>
select(shapeName, geometry)
qc_sf #geographic coordinate
Simple feature collection with 1 feature and 1 field
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: -72.97097 ymin: 45.58932 xmax: -71.37237 ymax: 46.561
Geodetic CRS: WGS84
shapeName geometry
1 Centre-du-Québec MULTIPOLYGON (((-72.03755 4...
plot(qc_sf$geometry)
Precipitation data
We will extract precipitation 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-monthly-means"
)
# List of available variables
vars_df <- KrigR::Meta.Variables(
"reanalysis-era5-land"
)
#extract precipitation data
start_date <- "1993-01-01 00:00"
end_date <- "2023-12-31 24:00"
precipitation_raw <- KrigR::CDownloadS(
Type = "monthly_averaged_reanalysis",
Variable = "total_precipitation",
DataSet = "reanalysis-era5-land-monthly-means",
DateStart = start_date,
DateStop = end_date,
TZone = "CET",
FUN = "mean",
TResolution = "month",
TStep = 1,
Dir = Dir.Data,
FileName = "precipitation_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 precipitation values for the region of interest.
# Change layer names
months_vector <- seq(
from = as.Date(start_date),
to = as.Date(end_date),
by = "month"
)
names(precipitation_raw) <- months_vector
# Raster to dataframe
precipitation_sf <- precipitation_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)) |>
select(x, y, date, year, month, value) |>
st_as_sf(coords=c("x", "y")) |>
st_set_crs("WGS84") |>
st_intersection(qc_sf)
precipitation_dt<-precipitation_sf |>
as_tibble() |>
select(-geometry) |>
group_by(shapeName, date, year, month) |>
summarise(mean=mean(value, na.rm=TRUE)) |>
ungroup()
General trend
Let’s start by exploring the precipitation data to understand its distribution and general trends.
skimr::skim(precipitation_dt)
Name | precipitation_dt |
Number of rows | 372 |
Number of columns | 5 |
_______________________ | |
Column type frequency: | |
character | 2 |
numeric | 3 |
________________________ | |
Group variables | None |
Data summary
Variable type: character
skim_variable | n_missing | complete_rate | min | max | empty | n_unique | whitespace |
---|---|---|---|---|---|---|---|
shapeName | 0 | 1 | 16 | 16 | 0 | 1 | 0 |
date | 0 | 1 | 10 | 10 | 0 | 372 | 0 |
Variable type: numeric
skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 | hist |
---|---|---|---|---|---|---|---|---|---|---|
year | 0 | 1 | 2008.0 | 8.96 | 1993 | 2000.00 | 2008.0 | 2016.00 | 2023.00 | ▇▇▇▇▇ |
month | 0 | 1 | 6.5 | 3.46 | 1 | 3.75 | 6.5 | 9.25 | 12.00 | ▇▅▅▅▇ |
mean | 0 | 1 | 0.0 | 0.00 | 0 | 0.00 | 0.0 | 0.00 | 0.01 | ▃▇▆▂▁ |
Trend over time
Is there a general trend over time? Let’s find out!
precipitation_dt_year<-precipitation_dt |>
group_by(year) |>
summarise(sum=sum(mean)) |>
ungroup()
ggplot(data=precipitation_dt_year, aes(x=year, y=sum))+
geom_line()
Precipitation has increased over time.
Space trend
Is there a general trend over space? Let’s find out!
sum<- terra::app(precipitation_raw, fun = "sum", na.rm = TRUE)
plot(sum)
The total precipitation for 30 years is different for each location in the raster, with les precipitation in the western section.
Spatio-temporal trend
Can we link the spatial trend to the temporal trend? Let’s find out!
precipitation_sf |>
mutate(lon = st_coordinates(geometry)[,1],
lat = st_coordinates(geometry)[,2]) |>
group_by(year, lon, lat) |>
summarise(sum=sum(value, na.rm=TRUE)*10000) |>
ungroup() |>
ggplot(aes(x=lon, y=lat, fill=sum))+
geom_tile()+
facet_wrap(~year)+
theme_map()+
scale_fill_viridis_c()+
labs(title="Distribution of Precipitations for Centre-du-Québec",
fill="Total (mm)")+
theme(legend.position = "bottom",
legend.justification = "center",
plot.title = element_text(hjust = 0, face = "bold", size=15.5))
This graph shows the spatial distribution of precipitation over time. The color intensity represents the amount of precipitation, with darker colors indicating higher values. This clearly indicates that precipitation levels vary across the region and the years.
Anomalies and outliers
Are there any anomalies or outliers in the precipitation data? Let’s investigate!
Time serie anomalies
What are the yearly precipitation anomalies?
library(anomalize)
precipitation_dt |>
group_by(shapeName, year) |>
summarize(value_year=sum(mean)*1000) |>
mutate(year_date=as.Date(as.character(year), "%Y")) |>
select(-year) |>
ungroup() |>
time_decompose(value_year) |>
anomalize(remainder) |>
plot_anomalies() +
labs(title="Anomalies of Precipitations (mm) for Centre-du-Québec")+
theme(plot.title = element_text(hjust = 0, face = "bold", size=15.5))
This graph shows the yearly precipitation anomalies in Centre-du-Québec over the past 30 years. The blue bars represent positive anomalies, while the red bars represent negative anomalies.
Weather anomalies
What are monthly precipitation anomalies?
library(anomalize)
precipitation_dt |>
group_by(shapeName, date) |>
summarize(value=sum(mean)) |>
mutate(date=as.Date(date)) |>
ungroup() |>
time_decompose(value) |>
anomalize(remainder) |>
plot_anomalies()+
labs(title="Anomalies of Precipitations (mm) for Centre-du-Québec")+
theme(plot.title = element_text(hjust = 0, face = "bold", size=15.5))
This graph does not show any monthly precipitation anomalies and does not show the seasonality of precipitation.
Let’s se I we can do better.
ggplot(precipitation_dt, aes(x = month, y = mean*1000, group = month)) +
geom_boxplot(fill="#DBBDC3")+
geom_dotplot(binaxis = "y", stackdir = "center", dotsize = 0.5, alpha=0.3)+
labs(title="Cummulative Monthly Precipitations (mm) for Centre-du-Québec 1993-2023",
x="Month",
y="Precipitation (mm)")+
theme(plot.title = element_text(hjust = 0, face = "bold", size=12),
axis.title.x = element_text(hjust = 0, face = "bold", size=8),
axis.title.y = element_text(hjust = 1, face = "bold", size=8))+
scale_x_continuous(breaks=seq(1,12,1), limits=c(0.5, 12.5))
We can clearly see that the precipitation levels vary across the month of the year, with higher levels during summers months.
Conclusion
In this post, we explored 30 years of high-resolution precipitation data for Centre-du-Québec, focusing on trends, patterns, and anomalies. Our analysis revealed several key insights:
-
General Trend – Precipitation levels have not significantly increased over the past 30 years. But in 2021-2023, the precipitation decreased.
-
Spatial Variation – Precipitation levels vary across the region, with higher levels in the western section.
-
Spatio-Temporal Trend – The spatial distribution of precipitation varies over time, with different patterns emerging each year.
-
Anomalies & Outliers – We identified yearly and monthly precipitation anomalies, highlighting unusual weather events and extreme precipitation periods.
This detailed analysis provides valuable insights into long-term precipitation dynamics in Centre-du-Québec, offering essential information for climate research, agriculture, and water resource management.
Session Info
sessionInfo()
R version 4.4.2 (2024-10-31)
Platform: aarch64-apple-darwin20
Running under: macOS Sequoia 15.2
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] grid stats graphics grDevices datasets utils methods
[8] base
other attached packages:
[1] anomalize_0.3.0 reticulate_1.40.0 jofou.lib_0.0.0.9000
[4] tidytuesdayR_1.1.2 tictoc_1.2.1 rgeoboundaries_1.3.1
[7] terra_1.8-10 sf_1.0-19 pins_1.4.0
[10] fs_1.6.5 timetk_2.9.0 yardstick_1.3.2
[13] workflowsets_1.1.0 workflows_1.1.4 tune_1.2.1
[16] rsample_1.2.1 parsnip_1.2.1 modeldata_1.4.0
[19] infer_1.0.7 dials_1.3.0 scales_1.3.0
[22] broom_1.0.7 tidymodels_1.2.0 recipes_1.1.0
[25] doFuture_1.0.1 future_1.34.0 foreach_1.5.2
[28] skimr_2.1.5 gganimate_1.0.9 forcats_1.0.0
[31] stringr_1.5.1 dplyr_1.1.4 purrr_1.0.2
[34] readr_2.1.5 tidyr_1.3.1 tibble_3.2.1
[37] ggplot2_3.5.1 tidyverse_2.0.0 lubridate_1.9.4
[40] kableExtra_1.4.0 inspectdf_0.0.12.1 openxlsx_4.2.7.1
[43] knitr_1.49
loaded via a namespace (and not attached):
[1] rstudioapi_0.17.1 jsonlite_1.8.9 wk_0.9.4
[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 s2_1.1.7
[16] TTR_0.24.4 parallelly_1.41.0 KernSmooth_2.23-26
[19] zoo_1.8-12 cachem_1.1.0 ggfittext_0.10.2
[22] lifecycle_1.0.4 iterators_1.0.14 pkgconfig_2.0.3
[25] Matrix_1.7-2 R6_2.5.1 fastmap_1.2.0
[28] digest_0.6.37 colorspace_2.1-1 furrr_0.3.1
[31] labeling_0.4.3 timechange_0.3.0 compiler_4.4.2
[34] proxy_0.4-27 withr_3.0.2 tseries_0.10-58
[37] backports_1.5.0 DBI_1.2.3 MASS_7.3-64
[40] lava_1.8.1 rappdirs_0.3.3 classInt_0.4-11
[43] tibbletime_0.1.9 tools_4.4.2 units_0.8-5
[46] lmtest_0.9-40 quantmod_0.4.26 zip_2.3.1
[49] future.apply_1.11.3 nnet_7.3-20 quadprog_1.5-8
[52] glue_1.8.0 nlme_3.1-166 generics_0.1.3
[55] gtable_0.3.6 countrycode_1.6.0 tzdb_0.4.0
[58] class_7.3-23 data.table_1.16.4 hms_1.1.3
[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] renv_1.0.7 survival_3.8-3 tidyselect_1.2.1
[70] urca_1.3-4 svglite_2.1.3 forecast_8.23.0
[73] crul_1.5.0 xfun_0.50 hardhat_1.4.0
[76] timeDate_4041.110 stringi_1.8.4 DiceDesign_1.10
[79] yaml_2.3.10 evaluate_1.0.3 codetools_0.2-20
[82] httpcode_0.3.0 cli_3.6.3 rpart_4.1.24
[85] systemfonts_1.2.1 repr_1.1.7 munsell_0.5.1
[88] Rcpp_1.0.14 globals_0.16.3 png_0.1-8
[91] parallel_4.4.2 fracdiff_1.5-3 assertthat_0.2.1
[94] gower_1.0.2 prettyunits_1.2.0 sweep_0.2.5
[97] GPfit_1.0-8 listenv_0.9.1 viridisLite_0.4.2
[100] ipred_0.9-15 xts_0.14.1 prodlim_2024.06.25
[103] e1071_1.7-16 crayon_1.5.3 rlang_1.1.5
- Posted on:
- January 29, 2025
- Length:
- 10 minute read, 1927 words
- Categories:
- rstats tidymodels tidytuesday eda viz
- Tags:
- eda rstats tidymodels tidytuesday viz