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.


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.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
See Also:
St. Lawrence Lowlands Precipitation Data: 30-Year Trends Prediction
St. Lawrence Lowlands Precipitation Data: 30-Year Trends & Anomalies
TyT2024W21 - VIZ:Carbon Majors Emissions Data