Mapping Weather Data
[2023-09-20] Until recently, this article was part of the documentation for the
weathercan
package. To simplify the docs while retaining this article, I’ve decided to move it here.This example is a bit dated (it isn’t the most modern approach), and is lacking in detailed explanations. However, I hope this is still useful as a more advanced example of how data can be combined using different types of tools.
This article is based on the blog post Integrating data from weathercan written for rOpenSci March 6th 2018.
In that article I demonstrated how we can incorporate data from weathercan
into spatial visualizations. In this article I’d like to take that even further and show you how you can create interactive maps which highlight spatial variability in weather data.
Here, we’ll take a look at annual temperatures throughout different Eco Regions in Manitoba, Canada.
Setup
Using extra CSS styles
The map that we create here may look different for you unless you include the tweaks to the CSS styles I have made. If you’re using RMarkdown, you can supply these as a custom .css file, or inline with the <style>
and </style>
tags (like below).
<style>
div.leaflet-popup-content-wrapper {
width: 700px;
height: 100%;
}
div.leaflet-popup-tip-container {
opacity: 0;
}
div.leaflet-popup-content {
width: 90% !important;
}
img {
max-width: 90% !important;
min-width: 90% !important;
border: none;
}
/* Fix the NA mis-alignment in the legend */
div.info.legend.leaflet-control br {
clear: both;
}
</style>
Loading packages
Download Manitoban Eco Regions shapefile
download.file("http://mli2.gov.mb.ca/environment/shp_zip_files/env_ecological_areas_py_shp.zip",
destfile = "ecological_shp.zip")
unzip("ecological_shp.zip")
file.remove("ecological_shp.zip")
[1] TRUE
Download Manitoba weather data
We’ll select all currently operating stations (end >= 2018
) and download the daily weather data for 2017:
mb <- filter(stations(), prov == "MB", interval == "day", end >= 2018)
w <- weather_dl(mb$station_id, start = "2017-01-01", end = "2017-12-31", interval = "day")
Calculating summaries
In this section, we’ll summarize our data and create the means of showcasing it in our map. We’ll calculate some basic summaries and we’ll style some popups to contain this information (including the figures we’ll create later).
We’ll do a station-specific summaries/pop-ups for when users click on a station marker, and region-specific ones for when they click on the region polygon.
Station summaries
mb_stations <- w %>%
group_by(station_id) %>%
mutate(n = n(),
n_missing = sum(is.na(mean_temp)),
mean_temp = mean(mean_temp, na.rm = TRUE)) %>%
filter((n - n_missing) > 0) %>% # Only keep stations with some temperature data
select(station_name, station_id, lat, lon, mean_temp, n, n_missing) %>%
distinct() %>%
mutate(station_name = tools::toTitleCase(tolower(station_name)),
info = paste0("<h3>Station: ", station_name, " (", station_id, ")</h2>",
"<hr>",
"<div>",
"<strong>Mean Temperature: </strong>", round(mean_temp, 1), "C<br>",
"<strong>No. days with data: </strong>", n-n_missing, "<br>",
"<strong>No. days total: </strong>", n, "</div>",
"<img src = 'svg/", station_id, ".svg'>"),
pretty_name = map(station_name,
~HTML(paste0("<strong>Station: </strong>", .x)))) %>%
ungroup() %>%
st_as_sf(coords = c("lon", "lat"), crs = "+proj=longlat")
Eco Region summaries
Before we summarize this data, we’ll filter the Eco Regions to just Manitoba and will join this to the stations data (after transforming the stations data to the same CRS), so we can figure out which stations belong to which regions.
mb_ecoregions <- st_read("env_ecological_areas.shp") %>%
filter(MANITOBA == "yes") %>%
# Get the larger-scale regions and combine
group_by(ECOREGION, REGION_NAM, REGION_NOM) %>%
summarize()
Reading layer `env_ecological_areas' from data source
`/home/steffi/Projects/AA Websites/steffilazerte.github.io/posts/weathercan-mapping/env_ecological_areas.shp'
using driver `ESRI Shapefile'
Simple feature collection with 279 features and 15 fields
Geometry type: POLYGON
Dimension: XY
Bounding box: xmin: -621621.3 ymin: 5386414 xmax: 1868189 ymax: 7166472
Projected CRS: NAD83 / UTM zone 14N
`summarise()` has grouped output by 'ECOREGION', 'REGION_NAM'. You can override
using the `.groups` argument.
mb_stations <- st_transform(mb_stations, crs = st_crs(mb_ecoregions))
mb_ecoregions <- st_join(mb_ecoregions, mb_stations) %>%
group_by(ECOREGION, REGION_NAM, REGION_NOM) %>%
summarize(n_stations = length(unique(station_id[!is.na(station_id)])),
mean_temp = mean(mean_temp, na.rm = TRUE),
mean_temp = replace(mean_temp, is.nan(mean_temp), NA),
.groups = "drop") %>%
mutate(info = paste0("<h3>Region: ", REGION_NAM, "/", REGION_NOM, " (", ECOREGION, ")</h2>",
"<hr>",
"<div>",
"<strong>Mean Temperature: </strong>", round(mean_temp, 1),
if_else(!is.na(mean_temp), "C<br>", "<br>"),
"<strong>No. stations: </strong>", n_stations, "</div>"),
info = if_else(n_stations > 0,
paste0(info, "<img src = 'svg/", ECOREGION, ".svg'>"),
info),
pretty_name = map(REGION_NAM,
~HTML(paste0("<strong>Region: </strong>", .x)))) %>%
ungroup()
Figures
We’ll set up some functions to create and save figures for our map
plot_station_fig <- function(d, station_id) {
g <- ggplot(d, aes(x = date, y = mean_temp)) +
theme_bw() +
geom_line(na.rm = TRUE) +
labs(x = "Date", y = "Mean Daily Temperature (C)")
ggsave(paste0("svg/", station_id, ".svg"), plot = g,
width = 6, height = 3, dpi = 100)
}
plot_region_fig <- function(d, region) {
g <- ggplot(d, aes(x = date, y = mean_temp,
group = station_name, colour = station_name)) +
theme_bw() +
geom_line(na.rm = TRUE) +
scale_colour_viridis_d(end = 0.8) +
labs(x = "Date", y = "Mean Daily Temperature (C)", colour = "Stations")
ggsave(paste0("svg/", region, ".svg"), plot = g,
width = 6, height = 3, dpi = 100)
}
Now we’ll apply these functions to our data. Note that this figs
object isn’t important, it’s just used as a way to loop through the data and save the figures as svg files.
dir.create("svg")
Warning in dir.create("svg"): 'svg' already exists
figs <- st_join(mb_stations, mb_ecoregions) %>%
st_drop_geometry %>%
left_join(select(w, station_id, date, mean_temp), by = "station_id") %>%
nest(data = -ECOREGION) %>%
mutate(fig_region = map2(data, ECOREGION, ~plot_region_fig(.x, .y))) %>%
unnest(data) %>%
nest(data = c(-ECOREGION, -station_id)) %>%
mutate(fig_station = map2(data, station_id, ~plot_station_fig(.x, .y)))
Mapping
Finally, we’re ready to create our map!
We’ll start by transforming our data into WGS84 for leaflet, then we’ll create a palette and get some icons…
# Required for Leaflet
mb_ecoregions <- st_transform(mb_ecoregions, crs = 4326)
mb_stations <- st_transform(mb_stations, crs = 4326)
# Setup Palette for polygons
pal_eco <- colorNumeric(palette = "viridis",
domain = mb_ecoregions$mean_temp)
# Get icons for stations (red if above average, blue if below)
station_icons <- awesomeIcons(iconColor = "black", library = "ion",
markerColor = ifelse(mb_stations$mean_temp >
mean(mb_stations$mean_temp,
na.rm = TRUE),
"red", "blue"))
Now for the real magic!
leaflet(width = "750px", height = "85vh") %>%
addTiles() %>%
addPolygons(data = mb_ecoregions,
color = "#444444", weight = 1, opacity = 1, fillOpacity = 0.5,
fillColor = ~pal_eco(mean_temp),
label = ~pretty_name, popup = ~info,
popupOptions = popupOptions(keepInView = TRUE),
highlightOptions = highlightOptions(bringToFront = TRUE,
fillOpacity = 1)) %>%
addAwesomeMarkers(data = mb_stations, group = "Stations",
icon = station_icons,
label = ~pretty_name, popup = ~info,
popupOptions = popupOptions(keepInView = TRUE)) %>%
addLegend("bottomright", pal = pal_eco,
values = mb_ecoregions$mean_temp,
title = "Mean region temperature",
labFormat = labelFormat(suffix = " C")) %>%
addLegend("bottomright",
title = "Station temperature",
colors = c("#d63e2a", "#37a7da"), opacity = 1,
labels = c("Above the average", "Below the average")) %>%
addLayersControl(
overlayGroups = "Stations",
options = layersControlOptions(collapsed = FALSE))
I think this is an interesting way of looking at the Eco Regions in Manitoba.
First we see a clear (and expected) pattern of decreasing temperatures with latitude (South to North). Further, we also see a bit of a South West to North East pattern.
Looking at the Eco Regions like this gives a clear idea of some of the parameters that make these Eco Regions distinct. For example, the patch of lands in the lower left corner of the province are the Mid-Boreal Uplands and the Boreal Transition. See how much cooler they are (on average) than the rest of southern Manitoba.
These southern Boreal regions represent a distinct ecology in southern Manitoba. If you zoom in on the map, you’ll see that they also hold two parks: Duck Mountain Provincial Park and Riding Mountain National Park.
Session Info
devtools::session_info()
─ Session info ───────────────────────────────────────────────────────────────
setting value
version R version 4.3.3 (2024-02-29)
os Ubuntu 22.04.4 LTS
system x86_64, linux-gnu
ui X11
language en_CA:en
collate en_CA.UTF-8
ctype en_CA.UTF-8
tz America/Winnipeg
date 2024-03-15
pandoc 3.1.1 @ /usr/lib/rstudio/resources/app/bin/quarto/bin/tools/ (via rmarkdown)
─ Packages ───────────────────────────────────────────────────────────────────
package * version date (UTC) lib source
bit 4.0.5 2022-11-15 [1] CRAN (R 4.3.0)
bit64 4.0.5 2020-08-30 [1] CRAN (R 4.3.0)
cachem 1.0.8 2023-05-01 [1] CRAN (R 4.3.0)
class 7.3-22 2023-05-03 [4] CRAN (R 4.3.1)
classInt 0.4-10 2023-09-05 [1] CRAN (R 4.3.1)
cli 3.6.2 2023-12-11 [1] CRAN (R 4.3.2)
codetools 0.2-19 2023-02-01 [4] CRAN (R 4.2.2)
colorspace 2.1-0 2023-01-23 [1] CRAN (R 4.3.0)
crayon 1.5.2 2022-09-29 [1] CRAN (R 4.3.0)
crosstalk 1.2.1 2023-11-23 [1] CRAN (R 4.3.2)
curl 5.2.1 2024-03-01 [1] CRAN (R 4.3.2)
DBI 1.2.2 2024-02-16 [1] CRAN (R 4.3.2)
devtools 2.4.5 2022-10-11 [1] CRAN (R 4.3.0)
digest 0.6.34 2024-01-11 [1] CRAN (R 4.3.2)
dplyr * 1.1.4 2023-11-17 [1] CRAN (R 4.3.2)
e1071 1.7-14 2023-12-06 [1] CRAN (R 4.3.2)
ellipsis 0.3.2 2021-04-29 [1] CRAN (R 4.3.0)
evaluate 0.23 2023-11-01 [1] CRAN (R 4.3.1)
fansi 1.0.6 2023-12-08 [1] CRAN (R 4.3.2)
farver 2.1.1 2022-07-06 [1] CRAN (R 4.3.0)
fastmap 1.1.1 2023-02-24 [1] CRAN (R 4.3.0)
fs 1.6.3 2023-07-20 [1] CRAN (R 4.3.1)
generics 0.1.3 2022-07-05 [1] CRAN (R 4.3.0)
ggplot2 * 3.5.0 2024-02-23 [1] CRAN (R 4.3.2)
glue 1.7.0 2024-01-09 [1] CRAN (R 4.3.2)
gridExtra 2.3 2017-09-09 [1] CRAN (R 4.3.0)
gtable 0.3.4 2023-08-21 [1] CRAN (R 4.3.1)
hms 1.1.3 2023-03-21 [1] CRAN (R 4.3.0)
htmltools * 0.5.7 2023-11-03 [1] CRAN (R 4.3.1)
htmlwidgets 1.6.4 2023-12-06 [1] CRAN (R 4.3.2)
httpuv 1.6.14 2024-01-26 [1] CRAN (R 4.3.2)
httr 1.4.7 2023-08-15 [1] CRAN (R 4.3.1)
jquerylib 0.1.4 2021-04-26 [1] CRAN (R 4.3.0)
jsonlite 1.8.8 2023-12-04 [1] CRAN (R 4.3.2)
KernSmooth 2.23-22 2023-07-10 [1] CRAN (R 4.3.1)
knitr 1.45 2023-10-30 [1] CRAN (R 4.3.1)
labeling 0.4.3 2023-08-29 [1] CRAN (R 4.3.1)
later 1.3.2 2023-12-06 [1] CRAN (R 4.3.2)
leaflet * 2.2.1 2023-11-13 [1] CRAN (R 4.3.2)
lifecycle 1.0.4 2023-11-07 [1] CRAN (R 4.3.2)
lubridate 1.9.3 2023-09-27 [1] CRAN (R 4.3.1)
lutz 0.3.2 2023-10-17 [1] CRAN (R 4.3.1)
magrittr 2.0.3 2022-03-30 [1] CRAN (R 4.3.0)
memoise 2.0.1 2021-11-26 [1] CRAN (R 4.3.0)
mime 0.12 2021-09-28 [1] CRAN (R 4.3.0)
miniUI 0.1.1.1 2018-05-18 [1] CRAN (R 4.3.0)
munsell 0.5.0 2018-06-12 [1] CRAN (R 4.3.0)
pillar 1.9.0 2023-03-22 [1] CRAN (R 4.3.0)
pkgbuild 1.4.3 2023-12-10 [1] CRAN (R 4.3.2)
pkgconfig 2.0.3 2019-09-22 [1] CRAN (R 4.3.0)
pkgload 1.3.3 2023-09-22 [1] CRAN (R 4.3.1)
profvis 0.3.8 2023-05-02 [1] CRAN (R 4.3.1)
promises 1.2.1 2023-08-10 [1] CRAN (R 4.3.1)
proxy 0.4-27 2022-06-09 [1] CRAN (R 4.3.0)
purrr * 1.0.2 2023-08-10 [1] CRAN (R 4.3.1)
R6 2.5.1 2021-08-19 [1] CRAN (R 4.3.0)
ragg 1.2.6 2023-10-10 [1] CRAN (R 4.3.1)
rappdirs 0.3.3 2021-01-31 [1] CRAN (R 4.3.0)
RColorBrewer 1.1-3 2022-04-03 [1] CRAN (R 4.3.0)
Rcpp 1.0.12 2024-01-09 [1] CRAN (R 4.3.2)
readr 2.1.5 2024-01-10 [1] CRAN (R 4.3.2)
remotes 2.4.2.1 2023-07-18 [1] CRAN (R 4.3.2)
rlang 1.1.3 2024-01-10 [1] CRAN (R 4.3.2)
rmarkdown 2.25 2023-09-18 [1] CRAN (R 4.3.1)
rstudioapi 0.15.0 2023-07-07 [1] CRAN (R 4.3.1)
s2 1.1.6 2023-12-19 [1] CRAN (R 4.3.2)
scales 1.3.0 2023-11-28 [1] CRAN (R 4.3.2)
sessioninfo 1.2.2 2021-12-06 [1] CRAN (R 4.3.0)
sf * 1.0-15 2023-12-18 [1] CRAN (R 4.3.2)
shiny 1.8.0 2023-11-17 [1] CRAN (R 4.3.2)
stringi 1.8.3 2023-12-11 [1] CRAN (R 4.3.2)
stringr * 1.5.1 2023-11-14 [1] CRAN (R 4.3.2)
svglite 2.1.3 2023-12-08 [1] CRAN (R 4.3.2)
systemfonts 1.0.5 2023-10-09 [1] CRAN (R 4.3.1)
textshaping 0.3.7 2023-10-09 [1] CRAN (R 4.3.1)
tibble 3.2.1 2023-03-20 [1] CRAN (R 4.3.0)
tidyr * 1.3.1 2024-01-24 [1] CRAN (R 4.3.2)
tidyselect 1.2.0 2022-10-10 [1] CRAN (R 4.3.0)
timechange 0.3.0 2024-01-18 [1] CRAN (R 4.3.2)
tzdb 0.4.0 2023-05-12 [1] CRAN (R 4.3.1)
units 0.8-5 2023-11-28 [1] CRAN (R 4.3.2)
urlchecker 1.0.1 2021-11-30 [1] CRAN (R 4.3.0)
usethis 2.2.2 2023-07-06 [1] CRAN (R 4.3.1)
utf8 1.2.4 2023-10-22 [1] CRAN (R 4.3.1)
vctrs 0.6.5 2023-12-01 [1] CRAN (R 4.3.2)
viridis 0.6.5 2024-01-29 [1] CRAN (R 4.3.2)
viridisLite 0.4.2 2023-05-02 [1] CRAN (R 4.3.1)
vroom 1.6.5 2023-12-05 [1] CRAN (R 4.3.2)
weathercan * 0.7.0.9000 2023-09-20 [1] local
withr 3.0.0 2024-01-16 [1] CRAN (R 4.3.2)
wk 0.9.1 2023-11-29 [1] CRAN (R 4.3.2)
xfun 0.42 2024-02-08 [1] CRAN (R 4.3.2)
xtable 1.8-4 2019-04-21 [1] CRAN (R 4.3.0)
yaml 2.3.8 2023-12-11 [1] CRAN (R 4.3.2)
[1] /home/steffi/R/x86_64-pc-linux-gnu-library/4.3
[2] /usr/local/lib/R/site-library
[3] /usr/lib/R/site-library
[4] /usr/lib/R/library
──────────────────────────────────────────────────────────────────────────────