Downloading Climate Normals
Climate Normals and Averages describe the average climate conditions
specific to a particular location. These can be downloaded from
Environment and Climate Change Canada using the
normals_dl() function.
First we’ll load the weathercan package for downloading
the data and the tidyr package for unnesting the data (see
below).
Downloading current normals (1991-2020)
To download climate normals, we’ll first find the stations we’re
interested in using the stations_search() function. We’ll
use the normals_years = "current" argument to filter to
only stations with the most recent available climate normals,
1991-2020.
stations_search("Winnipeg", normals_years = "current")## The most current normals available for download by weathercan are '1991-2020'
## # A tibble: 10 × 17
## prov station_name station_id climate_id WMO_id TC_id lat lon elev tz interval
## <chr> <chr> <dbl> <chr> <dbl> <chr> <dbl> <dbl> <dbl> <chr> <chr>
## 1 MB WINNIPEG A CS 27174 502S001 71849 XWG 49.9 -97.2 239. Etc/… day
## 2 MB WINNIPEG A CS 27174 502S001 71849 XWG 49.9 -97.2 239. Etc/… hour
## 3 MB WINNIPEG A CS 27174 502S001 71849 XWG 49.9 -97.2 239. Etc/… month
## 4 MB WINNIPEG INT… 51097 5023227 NA YWG 49.9 -97.2 239. Etc/… day
## 5 MB WINNIPEG INT… 51097 5023227 NA YWG 49.9 -97.2 239. Etc/… hour
## 6 MB WINNIPEG RIC… 47407 5023226 71852 YWG 49.9 -97.2 239. Etc/… day
## 7 MB WINNIPEG RIC… 47407 5023226 71852 YWG 49.9 -97.2 239. Etc/… hour
## 8 MB WINNIPEG RIC… 3698 5023222 71852 YWG 49.9 -97.2 239. Etc/… day
## 9 MB WINNIPEG RIC… 3698 5023222 71852 YWG 49.9 -97.2 239. Etc/… hour
## 10 MB WINNIPEG RIC… 3698 5023222 71852 YWG 49.9 -97.2 239. Etc/… month
Let’s look at the climate normals from one of these stations in
Winnipeg, MB. Note that unlike the weather_dl() function,
the normals_dl() function requires climate_id,
not station_id.
In contrast to previous climate normals the most recent normals are
provided as a single download from ECCC which is stored in a local data
cache, and then referenced by normals_dl().
If you haven’t already created a cache folder, weathercan will prompt
you to do so. Otherwise normals_dl() will load, format and
filter the cached data to the climate ids specified.
n <- normals_dl(climate_ids = "5023222")## The most current normals available for download by weathercan are '1991-2020'
## Using composite locations: WINNIPEG RICHARDSON (AIRPORT)
n## # A tibble: 325 × 314
## location_name prov composite_stations period_of_record element_group period
## <chr> <chr> <chr> <chr> <chr> <chr>
## 1 WINNIPEG RICHARDSON (AI… MB WINNIPEG A CS (50… Normal Temperature Jan
## 2 WINNIPEG RICHARDSON (AI… MB WINNIPEG A CS (50… Normal Temperature Feb
## 3 WINNIPEG RICHARDSON (AI… MB WINNIPEG A CS (50… Normal Temperature Mar
## 4 WINNIPEG RICHARDSON (AI… MB WINNIPEG A CS (50… Normal Temperature Apr
## 5 WINNIPEG RICHARDSON (AI… MB WINNIPEG A CS (50… Normal Temperature May
## 6 WINNIPEG RICHARDSON (AI… MB WINNIPEG A CS (50… Normal Temperature Jun
## 7 WINNIPEG RICHARDSON (AI… MB WINNIPEG A CS (50… Normal Temperature Jul
## 8 WINNIPEG RICHARDSON (AI… MB WINNIPEG A CS (50… Normal Temperature Aug
## 9 WINNIPEG RICHARDSON (AI… MB WINNIPEG A CS (50… Normal Temperature Sep
## 10 WINNIPEG RICHARDSON (AI… MB WINNIPEG A CS (50… Normal Temperature Oct
## # ℹ 315 more rows
The more recent climate normals actually reflect composite stations.
Stations included are stored in the composite_stations
column.
n$composite_stations[1]## [1] "WINNIPEG A CS (502S001); WINNIPEG INTL A (5023227); WINNIPEG RICHARDSON AWOS (5023226); WINNIPEG RICHARDSON INT'L A (5023222)"
So we can see that these climate normals are actually composed of several different stations mostly from the Airport.
Once you have used normals_dl() and have downloaded and
cached the normals data, you can also access the original, cached, data
from ECCC.
library(readr)
normals_file() # Location of the cached data (if you've downloaded it!)## [1] "~/.local/share/weathercan/1991-2020_Canadian_Climate_Normals_CANADA_Data.csv"
n_orig <- read_csv(normals_file())## Rows: 69068 Columns: 19
## ── Column specification ──────────────────────────────────────────────────────────────────
## Delimiter: ","
## chr (19): LOCATION_NAME, PROVINCE_OR_TERRITORY, PERIOD_OF_RECORD, ELEMENT_GROUP, NORMA...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
n_orig## # A tibble: 69,068 × 19
## LOCATION_NAME PROVINCE_OR_TERRITORY PERIOD_OF_RECORD ELEMENT_GROUP NORMALS_ELEMENT
## <chr> <chr> <chr> <chr> <chr>
## 1 BANFF AB Normal Temperature Daily Average (°C)
## 2 BANFF AB Normal Temperature StdDev Mean Monthly…
## 3 BANFF AB Normal Temperature Daily Maximum (°C)
## 4 BANFF AB Normal Temperature Daily Minimum (°C)
## 5 BANFF AB Normal Temperature Maximum Daily Mean …
## 6 BANFF AB Normal Temperature Maximum Daily Mean …
## 7 BANFF AB Normal Temperature Minimum Daily Mean …
## 8 BANFF AB Normal Temperature Minimum Daily Mean …
## 9 BANFF AB Normal Temperature Extreme Maximum (°C)
## 10 BANFF AB Normal Temperature Extreme Maximum (°C…
## # ℹ 69,058 more rows
Downloading previous normals (1981-2010 and 1971-2000)
Similar to current normals, we first find the stations and then download the normals. The main difference is specifying that we want older normals, and then dealing with the different format these normals come in.
stations_search("Winnipeg", normals_years = "1981-2010")## # A tibble: 3 × 17
## prov station_name station_id climate_id WMO_id TC_id lat lon elev tz interval
## <chr> <chr> <dbl> <chr> <dbl> <chr> <dbl> <dbl> <dbl> <chr> <chr>
## 1 MB WINNIPEG RICH… 3698 5023222 71852 YWG 49.9 -97.2 239. Etc/… day
## 2 MB WINNIPEG RICH… 3698 5023222 71852 YWG 49.9 -97.2 239. Etc/… hour
## 3 MB WINNIPEG RICH… 3698 5023222 71852 YWG 49.9 -97.2 239. Etc/… month
n <- normals_dl(climate_ids = "5023222", normals_years = "1981-2010")
n## # A tibble: 1 × 7
## prov station_name climate_id normals_years meets_wmo normals frost
## <chr> <chr> <chr> <chr> <lgl> <list> <list>
## 1 MB WINNIPEG RICHARDSON INT'L A 5023222 1981-2010 TRUE <tibble> <tibble>
In older climate normals, there are two different data formats (one for weather measurements and one for first/last frost dates). Therefore, the data are nested as two different datasets. We can see that the Airport (Richardson Int’l) has 197 average weather measurements/codes as well as first/last frost dates.
Note that these older normals do not use composite stations.
We can also see that this station has data quality sufficient to meet the WMO standards for temperature and precipitation (i.e. both these measurements have code >= A). See the ECCC calculations document for more details.
To extract either data set we can use the unnest()
function from the tidyr package.
Note that this extracts the measurements for all three stations (in
the case of the normals data frame), but not all
measurements are available for each station
normals## # A tibble: 13 × 203
## prov station_name climate_id normals_years meets_wmo period temp_daily_average
## <chr> <chr> <chr> <chr> <lgl> <fct> <dbl>
## 1 MB WINNIPEG RICHARDSON… 5023222 1981-2010 TRUE Jan -16.4
## 2 MB WINNIPEG RICHARDSON… 5023222 1981-2010 TRUE Feb -13.2
## 3 MB WINNIPEG RICHARDSON… 5023222 1981-2010 TRUE Mar -5.8
## 4 MB WINNIPEG RICHARDSON… 5023222 1981-2010 TRUE Apr 4.4
## 5 MB WINNIPEG RICHARDSON… 5023222 1981-2010 TRUE May 11.6
## 6 MB WINNIPEG RICHARDSON… 5023222 1981-2010 TRUE Jun 17
## 7 MB WINNIPEG RICHARDSON… 5023222 1981-2010 TRUE Jul 19.7
## 8 MB WINNIPEG RICHARDSON… 5023222 1981-2010 TRUE Aug 18.8
## 9 MB WINNIPEG RICHARDSON… 5023222 1981-2010 TRUE Sep 12.7
## 10 MB WINNIPEG RICHARDSON… 5023222 1981-2010 TRUE Oct 5
## 11 MB WINNIPEG RICHARDSON… 5023222 1981-2010 TRUE Nov -4.9
## 12 MB WINNIPEG RICHARDSON… 5023222 1981-2010 TRUE Dec -13.2
## 13 MB WINNIPEG RICHARDSON… 5023222 1981-2010 TRUE Year 3
Let’s take a look at the frost data.
frost## # A tibble: 7 × 14
## prov station_name climate_id normals_years meets_wmo normals frost_code
## <chr> <chr> <chr> <chr> <lgl> <list> <chr>
## 1 MB WINNIPEG RICHARDSON INT'L A 5023222 1981-2010 TRUE <tibble> A
## 2 MB WINNIPEG RICHARDSON INT'L A 5023222 1981-2010 TRUE <tibble> A
## 3 MB WINNIPEG RICHARDSON INT'L A 5023222 1981-2010 TRUE <tibble> A
## 4 MB WINNIPEG RICHARDSON INT'L A 5023222 1981-2010 TRUE <tibble> A
## 5 MB WINNIPEG RICHARDSON INT'L A 5023222 1981-2010 TRUE <tibble> A
## 6 MB WINNIPEG RICHARDSON INT'L A 5023222 1981-2010 TRUE <tibble> A
## 7 MB WINNIPEG RICHARDSON INT'L A 5023222 1981-2010 TRUE <tibble> A
Finding stations with specific measurements
The included data frame, normals_measurements contains a
list of stations with their corresponding measurements. Be aware that
this data might be out of date!
normals_measurements## # A tibble: 376,959 × 6
## prov station_name climate_id normals measurement_type measurement
## <chr> <chr> <chr> <chr> <chr> <chr>
## 1 AB BANFF 3050520, 3050521, 3050519 1991-2020 Temperature daily_average_c
## 2 AB BANFF 3050520, 3050521, 3050519 1991-2020 Temperature stddev_mean_mo…
## 3 AB BANFF 3050520, 3050521, 3050519 1991-2020 Temperature daily_maximum_c
## 4 AB BANFF 3050520, 3050521, 3050519 1991-2020 Temperature daily_minimum_c
## 5 AB BANFF 3050520, 3050521, 3050519 1991-2020 Temperature maximum_daily_…
## 6 AB BANFF 3050520, 3050521, 3050519 1991-2020 Temperature maximum_daily_…
## 7 AB BANFF 3050520, 3050521, 3050519 1991-2020 Temperature minimum_daily_…
## 8 AB BANFF 3050520, 3050521, 3050519 1991-2020 Temperature minimum_daily_…
## 9 AB BANFF 3050520, 3050521, 3050519 1991-2020 Temperature extreme_maximu…
## 10 AB BANFF 3050520, 3050521, 3050519 1991-2020 Temperature extreme_maximu…
## # ℹ 376,949 more rows
Because the new climate normals are so different from previous years,
they include different measurements which are organized by
measurement_type. In older normals years,
measurement_type is NA.
For example, if you wanted all climate_ids for stations
that have data on temperature for 1991-2020 normals:
library(stringr) # text pattern matching
# Have a quick look
normals_measurements |>
filter(str_detect(measurement_type, "Temp"), normals == "1991-2020")## # A tibble: 21,528 × 6
## prov station_name climate_id normals measurement_type measurement
## <chr> <chr> <chr> <chr> <chr> <chr>
## 1 AB BANFF 3050520, 3050521, 3050519 1991-2020 Temperature daily_average_c
## 2 AB BANFF 3050520, 3050521, 3050519 1991-2020 Temperature stddev_mean_mo…
## 3 AB BANFF 3050520, 3050521, 3050519 1991-2020 Temperature daily_maximum_c
## 4 AB BANFF 3050520, 3050521, 3050519 1991-2020 Temperature daily_minimum_c
## 5 AB BANFF 3050520, 3050521, 3050519 1991-2020 Temperature maximum_daily_…
## 6 AB BANFF 3050520, 3050521, 3050519 1991-2020 Temperature maximum_daily_…
## 7 AB BANFF 3050520, 3050521, 3050519 1991-2020 Temperature minimum_daily_…
## 8 AB BANFF 3050520, 3050521, 3050519 1991-2020 Temperature minimum_daily_…
## 9 AB BANFF 3050520, 3050521, 3050519 1991-2020 Temperature extreme_maximu…
## 10 AB BANFF 3050520, 3050521, 3050519 1991-2020 Temperature extreme_maximu…
## # ℹ 21,518 more rows
ids <- normals_measurements |>
filter(str_detect(measurement_type, "Temp"), normals == "1991-2020") |>
pull(climate_id) |>
unique()Alternatively, if you wanted all climate_ids for
stations that have data on soil temperature for 1981-2010 normals (which
is no longer available in the 1991-2020 normals):
# Have a quick look
normals_measurements |>
filter(stringr::str_detect(measurement, "soil"), normals == "1981-2010")## # A tibble: 314 × 6
## prov station_name climate_id normals measurement_type measurement
## <chr> <chr> <chr> <chr> <chr> <chr>
## 1 AB BEAVERLODGE CDA 3070560 1981-2010 <NA> soil_temp_am_5
## 2 AB BEAVERLODGE CDA 3070560 1981-2010 <NA> soil_temp_am_5_code
## 3 AB BEAVERLODGE CDA 3070560 1981-2010 <NA> soil_temp_am_10
## 4 AB BEAVERLODGE CDA 3070560 1981-2010 <NA> soil_temp_am_10_code
## 5 AB BEAVERLODGE CDA 3070560 1981-2010 <NA> soil_temp_am_20
## 6 AB BEAVERLODGE CDA 3070560 1981-2010 <NA> soil_temp_am_20_code
## 7 AB BEAVERLODGE CDA 3070560 1981-2010 <NA> soil_temp_am_50
## 8 AB BEAVERLODGE CDA 3070560 1981-2010 <NA> soil_temp_am_50_code
## 9 AB BEAVERLODGE CDA 3070560 1981-2010 <NA> soil_temp_am_100
## 10 AB BEAVERLODGE CDA 3070560 1981-2010 <NA> soil_temp_am_100_code
## # ℹ 304 more rows
ids <- normals_measurements |>
filter(stringr::str_detect(measurement, "soil"), normals == "1981-2010") |>
pull(climate_id) |>
unique()Understanding Climate Normals
The measurements contained in the climate normals are very specific. To better understand how they are calculated please explore the following resources:
- ECCC Climate Normals Calculations (1991-2020 | (1981-2010 | 1971-2000)
- ECCC Climate Normals Technical Documentation
