Historic UK Meteorological & Climate Data

line chart
climate
Published

October 21, 2025

Code
# TidyTuesday 2025-10-21 - Historic UK Meteorological & Climate Data

# 1. SETUP ------------------------------------------------------

library(pacman)
pacman::p_load(tidyverse, tidytuesdayR, dplyr, showtext, ggtext, scales)

tuesdata <- tidytuesdayR::tt_load('2025-10-21')
historic_station_met <- tuesdata$historic_station_met

# 2. DATA WRANGLING -----------------------------------------------

rainfall_year <- historic_station_met |> 
  select(station, year, month, rain) |> 
  na.omit() |> 
  group_by(year, month) |> 
  summarise(avg = mean(rain)) |> 
  ungroup()

rainfall_month <- rainfall_year |> 
  group_by(month) %>% 
  summarise(avg2 = mean(avg)) |> 
  ungroup()

rainfall_avg <- max(rainfall_year$avg)
wettest_year <- filter(rainfall_year, avg == rainfall_avg) |> pull(year)
wettest_month <- filter(rainfall_year, avg == rainfall_avg) |> pull(month)

rainfall_min <- min(rainfall_year$avg)
driest_year <- filter(rainfall_year, avg == rainfall_min) |> pull(year)
driest_month <- filter(rainfall_year, avg == rainfall_min) |> pull(month)

month_labels <- c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
                "Aug", "Sep", "Oct", "Nov", "Dec")

# 3. PLOT ---------------------------------------------------------

font_add_google("Outfit", "title_font")
font_add_google("Roboto", "body_font")
showtext_auto()

rainfall_year |>
  mutate(
    month_label = factor(month, levels = 1:12, labels = month_labels),
    is_wettest = (year == wettest_year & month == wettest_month),
    is_driest = (year == driest_year & month == driest_month)
  ) |>
  ggplot(aes(x = year, y = avg)) +
  geom_line(aes(group = month_label),
            color = "#69b3a2",
            alpha = 0.3,
            linewidth = 0.5) +
  
  # Arrow to wettest point
  annotate("segment",
           x = wettest_year,
           xend = wettest_year,
           y = rainfall_avg + 15,
           yend = rainfall_avg + 2,
           arrow = arrow(length = unit(0.3, "cm"), type = "closed"),
           color = "#e63946",
           linewidth = 0.8) +
  
  # Arrow to driest point
  annotate("segment",
           x = driest_year,
           xend = driest_year,
           y = rainfall_min - 10,
           yend = rainfall_min - 1,
           arrow = arrow(length = unit(0.3, "cm"), type = "closed"),
           color = "#f4a261",
           linewidth = 0.8) +
  
  # Annotation for wettest
  annotate("text",
           x = wettest_year,
           y = rainfall_avg + 17,
           label = paste0("Wettest: ", month_labels[wettest_month], " ", wettest_year, "\n", 
                         round(rainfall_avg, 1), " mm"),
           family = "body_font",
           size = 3.5,
           fontface = "bold",
           color = "#e63946",
           hjust = 0.5,
           vjust = 0) +
  
  # Annotation for driest
  annotate("text",
           x = driest_year,
           y = rainfall_min - 12,
           label = paste0("Driest: ", month_labels[driest_month], " ", driest_year, "\n", 
                         round(rainfall_min, 1), " mm"),
           family = "body_font",
           size = 3.5,
           fontface = "bold",
           color = "#f4a261",
           hjust = 0.5,
           vjust = 1) +
  
  scale_x_continuous(breaks = seq(min(rainfall_year$year),
                                  max(rainfall_year$year),
                                  by = 10)) +
  scale_y_continuous(labels = label_number(suffix = " mm")) +

  labs(
    title = "Historic UK Rainfall Patterns",
    subtitle = "Monthly average rainfall across UK meteorological stations (1853-2023)",
    x = NULL,
    y = NULL,
    caption = "Data: UK Met Office | #TidyTuesday | @anabodevan"
  ) +
  
  theme_minimal(base_family = "body_font") +
  theme(
    plot.title = element_text(
      family = "title_font",
      size = 24,
      face = "bold",
      margin = margin(b = 10)
    ),
    plot.subtitle = element_text(
      size = 12,
      color = "grey30",
      margin = margin(b = 20)
    ),
    plot.caption = element_text(
      size = 9,
      color = "grey50",
      hjust = 1,
      margin = margin(t = 15)
    ),
    axis.title = element_text(size = 11, face = "bold"),
    axis.text = element_text(size = 10),
    panel.grid.minor = element_blank(),
    panel.grid.major = element_line(color = "grey90", linewidth = 0.3),
    plot.background = element_rect(fill = "white", color = NA),
    plot.margin = margin(20, 20, 20, 20)
  )