Evidence base for 2025 Environment Plan

Author
Affiliations

Steve Crawshaw

West of England Combined Authority

Published

October 29, 2025

Abstract

Data and analysis to support the 2025 Environment Plan.

Keywords

Carbon Reduction, Energy Efficiency, Regional Emissions

Show/Hide Code
# Pacman simplifies library loading by installing and loading in one step.
pacman::p_load(
  tidyverse, janitor, readxl, glue, fs, duckdb, arrow, DBI, gt, gtExtras, 
  treemapify, openair, ggtext, patchwork, showtext, fs, ragg, timetk
)
Show/Hide Code
## AMENDED: Created a function to avoid repeating the JSON parsing logic.
# This function fetches a colour palette from the WECA brand guidelines.
fetch_weca_palette <- function(palette_type) {
  jsonlite::read_json(
    "https://raw.githubusercontent.com/westofengland-ca/weca_templates/refs/heads/main/General_branding/brand_guidelines.json"
  ) |>
    pluck(3, "colors", palette_type) |>
    map_chr("hex") |>
    unname()
}

weca_primary_palette <- fetch_weca_palette("primary_colors")
weca_secondary_palette <- fetch_weca_palette("secondary_colors")

1 Introduction

This document brings together data and analysis to support the West of England Combined Authority’s 2025 Environment Plan. It includes information on regional emissions, energy use and home heating.

2 Data Sources

The primary data sources used in this analysis include:
- Sub - national total final energy consumption (DESNZ)
- UK local authority and regional carbon dioxide emissions national statistics (DESNZ)

North Somerset council is included in the West of England data throughout this document. The intention is for North Somerset to join the Mayoral Combined Authority in due course.

Show/Hide Code
# Connect to the EPC database
con_epc <- dbConnect(duckdb::duckdb("../mca-data/data/ca_epc.duckdb"))
invisible(dbExecute(con_epc, "INSTALL spatial"))
invisible(dbExecute(con_epc, "LOAD spatial"))

# Query necessary tables
ca_la_tbl <- dbGetQuery(con_epc, "FROM ca_la_tbl")
ghg_emissions_tbl <- dbGetQuery(con_epc, "FROM ghg_emissions_tbl")
emissions_tbl <- dbGetQuery(con_epc, "FROM emissions_tbl")
epc_domestic_lep_tbl <- dbGetQuery(con_epc, "FROM epc_domestic_lep_vw")
epc_non_domestic_tbl <- dbGetQuery(con_epc, "FROM epc_non_domestic_vw")

# Get names and codes for WECA and North Somerset local authorities
weca_ns_la_codes <- ca_la_tbl |> 
  filter(cauthnm == "West of England") |> 
  pull(ladcd)

weca_ns_la_names <- ca_la_tbl |> 
  filter(cauthnm == "West of England") |> 
  pull(ladnm)

# Create a named vector of 4 colours for plots
weca_palette_4 <- weca_primary_palette[2:5] |>
  set_names(weca_ns_la_names)
Show/Hide Code
# Connect to the energy database
con_env <- dbConnect(duckdb::duckdb("data/regional_energy.duckdb"))
invisible(dbExecute(con_env, "LOAD SPATIAL"))

# Query electricity table
electricity_la_tbl <- dbGetQuery(con_env, "FROM electricity_la_tbl")
energy_data_all_la_tbl <- dbGetQuery(con_env, "FROM energy_la_year_fuel_sector_long_vw")
Show/Hide Code
# Determine the most recent year available in the energy dataset
max_year <- max(energy_data_all_la_tbl$calendar_year)

# The original if/else was overly complex and used a non-existent function.
latest_epc_date <- as.Date(max(epc_domestic_lep_tbl$LODGEMENT_DATE))

# Format the date for use in plot titles and text
epc_date <- strftime(latest_epc_date, format = "%B %Y")

3 Renewable Energy Generation

Show/Hide Code
renewable <- tbl(con_env, "renewable_la_long_tbl")

max_renewable_year <- renewable |>
  summarise(max_year = max(calendar_year, na.rm = TRUE)) |>
  pull(max_year)

renewable_generation_latest_year_tbl <- 
  renewable |> 
  filter(local_authority_code %in% weca_ns_la_codes,
  calendar_year == max_renewable_year,
  type == "Generation",
  energy_source != "total",
  value > 0) |>
  collect() |> 
  mutate(Source = str_replace_all(energy_source, "_", " ") |>
    str_to_sentence(),
gen_GWH = value / 1000) 

Photovoltaics dominate renewable energy generation in the West of England, followed by onshore wind. The chart below shows renewable energy generation by source and local authority for the most recent year available, which is 2024. Total renewable generation in the West of England in that year was approximately 414 GWh.

Show/Hide Code
renewable_plot_gg <- 
renewable_generation_latest_year_tbl |>
  ggplot(aes(
x = Source,
y = gen_GWH,
fill = local_authority_name
)) +
  geom_col(position = "stack") +
    scale_fill_manual(values = weca_palette_4) +
      labs(
    title = ("Renewable Energy Generation"),
    subtitle = glue("WECA Local Authorities in {max_renewable_year}"),
    caption = "Source: DESNZ Regional Renewable Statistics",
    x = "Renewable Energy Source",
    y = "GWh",
    fill = "Local Authority"
  ) +
    theme_minimal() +
      theme(
    plot.title = element_text(face = "bold", size = 14, hjust = 0),
    plot.caption = element_text(size = 10),
    legend.position = "right",
    legend.key.size = unit(0.5, "cm"),
    legend.text = element_text(size = 10),
    legend.title = element_text(size = 12),
    strip.text = element_text(size = 14),
    axis.title.x = element_text(size = 12),
    axis.title.y = element_text(size = 12),
    axis.text = element_text(size = 10, face = "bold")
  ) +
    coord_flip()

renewable_plot_gg  

4 Fossil Fuel Generation

Show/Hide Code
seabank_tbl <- tbl(con_env, "seabank_tbl") |>
    group_by(date = as.Date(halfhourendtime), bmunit) |>
    summarise(
        generation_mwh = sum(generation_mwh, na.rm = TRUE),
        .groups = "drop"
    ) |>
    arrange(bmunit, date) |>
    collect()

total_gwh <- dbGetQuery(
    con_env,
    "SELECT sum(generation_mwh) / 1000 AS generation_gwh FROM seabank_tbl"
) |>
    pull()

year_fossil <- dbGetQuery(
    con_env,
    "SELECT year(min(halfhourendtime)) FROM seabank_tbl"
) |>
    pull()

percent_renewable_generation <- (sum(renewable_generation_latest_year_tbl$gen_GWH) * 100 / (total_gwh + sum(renewable_generation_latest_year_tbl$gen_GWH))) |> round()

There is one fossil fuel power station in the West of England, at Avonmouth. It is a combined cycle gas turbine (CCGT) plant with a capacity of 1234 MW operated by Seabank Power Ltd. Generation data for 2024 were retrieved from the Elexon API for each settlement period in 2024. The total generation from the plant in 2024 was approximately 3,597 GWh.

So in 2024, renewable generation in the West of England was approximately 10% of the total electricity generated.

Show/Hide Code
seabank_plotly <- seabank_tbl |>
    plot_time_series(
        .date_var = date,
        .value = generation_mwh,
        .color_var = bmunit,
        .smooth = FALSE,
        .facet_vars = bmunit,
        .facet_ncol = 2,
        .title = "Seabank Power Station Generation by Generating Unit",
        .x_lab = "Date",
        .y_lab = "Generation (MWh)"
    )

seabank_gg <- seabank_tbl |>
    ggplot(aes(x = date, y = generation_mwh, color = bmunit)) +
    geom_line() +
    facet_wrap(~bmunit, ncol = 1) +
    labs(
        title = "Seabank Power Station",
        subtitle = glue("Daily total generation by generating unit in {year_fossil}"),
        x = "Date",
        y = "Generation (MWh)",
        color = "Generating Unit"
    ) +
      scale_color_manual(values = weca_primary_palette[2:3]) +
    theme_minimal()

The plot below shows the daily generation from each of the two generating units at Seabank Power Station in 2024.

Show/Hide Code
seabank_gg

5 Energy Consumption and Fuel Types

Transport uses the largest share of energy in the West of England, closely followed by domestic and then industry, commercial and other users. The data below is for all energy consumption in the West of England in 2023. Almost all transport energy use is from petroleum products.

Show/Hide Code
total_energy_weca <- sum(energy_data_weca_max_year_all_fuels_tbl$energy_gwh)

min_year <- min(energy_data_all_la_tbl$calendar_year)

change_energy_consumption_weca <- energy_data_all_la_tbl |>
  filter(
    ladcd %in% weca_ns_la_codes,
    fuel == "All fuels",
    sector == "Total",
    calendar_year %in% c(min_year, max_year)
  ) |>
  group_by(calendar_year) |>
  summarise(total_energy_gwh = sum(gigatonnes_oil_equivalent * 11.63), .groups = "drop") |>
  arrange(calendar_year) |>
  mutate(
    change_gwh = total_energy_gwh - lag(total_energy_gwh),
    pct_change = change_gwh / lag(total_energy_gwh) * 100
  )

change_pct_energy_weca <- round(change_energy_consumption_weca$pct_change[2])

Total energy consumption in the West of England in 2023 was approximately 21,514 GWh. This is a drop of 19% since 2005.

Sector Contribution (2023)
Car Side Transport 41%
House Domestic 32%
Industry Industrial commercial and other 28%

A pie chart representation of the energy consumption by end user sector is shown below.

Show/Hide Code
## AMENDED: URL updated to download Font Awesome v4.7.0 as required.
# This ensures the correct font version is used for reproducibility.
fa_font_path <- "fontawesome/fontawesome-webfont.ttf"
if (!file.exists(fa_font_path)) {
  dir_create("fontawesome")
  download.file(
    "https://raw.githubusercontent.com/FortAwesome/Font-Awesome/v4.7.0/fonts/fontawesome-webfont.ttf",
    destfile = fa_font_path,
    mode = "wb"
  )
}
font_add(family = "fontawesome", regular = fa_font_path)

# Enable showtext for this chunk
showtext_auto()

# Prepare data for plotting
pie_data_tbl <- energy_data_weca_max_year_all_fuels_tbl |>
  select(sector, pct_sector) |>
  mutate(
    value = round(pct_sector * 100),
    icon = case_when(
      sector == "Domestic" ~ "\uf015", # fa-home
      sector == "Industrial commercial and other" ~ "\uf275", # fa-industry
      sector == "Transport" ~ "\uf1b9" # fa-car
    )
  ) |>
  # Arrange for consistent plotting order
  arrange(match(sector, c("Industry commercial and other", "Transport", "Domestic"))) |>
  mutate(
    y_pos = cumsum(value) - 0.5 * value,
    label_text = paste0(value, "%")
  )

# Define colours for the plot
bg_color <- "#1A2A3A"
line_color <- "#A8B820"

# Create the plot
pie_chart <- ggplot(pie_data_tbl, aes(x = 2, y = value)) +
  geom_col(width = 1.8, color = line_color, fill = bg_color, linewidth = 0.5) +
  geom_text(aes(x = 3.1, y = y_pos, label = label_text), color = line_color, fontface = "bold", size = 14) +
  geom_text(aes(x = 2, y = y_pos, label = icon), family = "fontawesome", size = 15, color = line_color) +
  coord_polar(theta = "y", start = pi / 2, direction = -1) +
  xlim(c(0.5, 3.2)) +
  theme_void() +
  theme(
    plot.background = element_rect(fill = bg_color, color = NA),
    panel.background = element_rect(fill = bg_color, color = NA)
  )

# Disable showtext after the plot is created
showtext_auto(enable = FALSE)

pie_chart

6 Energy Consumption by Fuel Type

Most energy consumed in the West of England is from petroleum products. The data below is for all energy consumption in the West of England in 2023.

Fuel Contribution (2023) Percentage
of total energy
Oil Well Petroleum
43
Fire Flame Simple Gas
33
Bolt Lightning Electricity
19
Leaf Other
5

7 Home Heating: Fuel Types

Analysis of the main heating fuel type in homes with an Energy Performance Certificate (EPC) in the West of England. The data is current to August 2025. Only around 70% of homes in the West of England have an EPC. The main heat classification in the data is not always precisely defined, so the categories below are broad groupings and classified from the original data using a large language model. In the visualisations and table below the “Two or more fuels” category has been excluded as the numbers are very small and uncertain, and all renewable heating types (biomass, solar, heat pumps) have been grouped together.

Show/Hide Code
fuel_types_homes_plot <- fuel_types_homes_plot_tbl |>
  ggplot(aes(x = n, y = category)) + ## AMENDED: Swapped x and y aesthetics, removed coord_flip() for simplicity.
  geom_col(fill = weca_primary_palette[1], show.legend = FALSE) +
  scale_x_continuous(labels = scales::comma) +
  scale_y_discrete(labels = function(x) str_wrap(x, width = 20)) +
  labs(
    title = "Main heating fuel type in homes with an EPC",
    subtitle = glue("West of England homes with an EPC to {epc_date}"),
    x = "Number of homes",
    y = NULL,
    caption = "Source: MHCLG"
  ) +
  theme_weca_bar()

fuel_types_homes_plot

Show/Hide Code
fuel_types_homes_single_bar <- fuel_types_homes_plot_tbl |>
  ggplot(aes(x = 1, y = n, fill = category)) +
  geom_col(position = "stack", show.legend = TRUE) + ## AMENDED: Explicitly set position = "stack" for clarity.
  coord_flip() +
  scale_y_continuous(labels = scales::comma) +
  scale_fill_manual(values = weca_palette_6) +
  guides(fill = guide_legend(reverse = TRUE)) +
  labs(
    title = "Main heating fuel type in homes with an EPC",
    subtitle = glue("Homes in the West of England with an EPC to {epc_date}"),
    x = NULL,
    y = "Number of homes",
    fill = "Fuel type",
    caption = "Source: MHCLG"
  ) +
  theme_weca_bar() +
  theme(
    axis.text.y = element_blank(),
    axis.ticks.y = element_blank(), ## AMENDED: Also remove ticks for a cleaner look.
    plot.title.position = "plot", ## AMENDED: Better way to align title than manual hjust.
    plot.subtitle = element_text(hjust = 0) ## AMENDED: Simpler alignment.
  )

fuel_types_homes_single_bar

Main heating fuel type in homes with an EPC
West of England homes with an EPC to August 2025
Main heating fuel type Number of homes Percentage of homes
Mains gas 294,942 80%
Electricity 47,486 13%
Community heating scheme 13,778 4%
Oil 7,349 2%
Renewable (inc. heat pumps) 4,088 1%
Other and unknown 2,781 1%
Source: MHCLG

8 Energy Consumption Over Time by Local Authority

Show/Hide Code
energy_weca_plot <- energy_weca_plot_tbl |>
  ggplot(aes(x = calendar_year, y = gwh, fill = ladnm)) +
  geom_col() +
  scale_y_continuous(labels = scales::comma) +
  scale_x_continuous(breaks = seq(start_year, max_year, by = 1)) +
  scale_fill_manual(values = weca_palette_4) +
  labs(
    title = "Total energy consumption (GWh)",
    subtitle = glue("West of England local authorities, {start_year}-{max_year}"),
    x = "Year",
    y = "GWh",
    fill = "Local authority",
    caption = "Source: Sub-national total final energy consumption"
  ) +
  coord_flip() +
  theme_weca_bar()

energy_weca_plot

9 Emissions by Local Authority

The treemap below shows the total territorial emissions in Kilotonnes of CO2 equivalent (KtCO2e) for each local authority in the West of England for the most recent year available, which is 2023.

Show/Hide Code
emissions_treemap_plot <- emissions_data_weca_max_year_tbl |>
  ggplot(aes(
    area = total_emissions,
    fill = local_authority,
    label = glue("{round(total_emissions, 0)}\n{local_authority}")
  )) +
  geom_treemap() +
  geom_treemap_text(
    colour = "white",
    place = "topleft",
    min.size = 4,
    grow = FALSE,
    reflow = TRUE
  ) +
  scale_fill_manual(values = weca_palette_4) +
  labs(
    title = glue("Total territorial emissions by local authority, {max_year} (KtCO2e)"),
    caption = "Source: UK local authority and regional greenhouse gas emissions statistics",
    fill = "Local authority"
  ) +
  theme_minimal() + 
  theme(
    legend.position = "none",
    plot.title = element_text(size = 20, face = "bold", hjust = 0.5, margin = margin(b = 10))
  )

emissions_treemap_plot

10 Emissions Over Time by Local Authority

Show/Hide Code
emissions_weca_plot <- emissions_weca_plot_tbl |>
  ggplot(aes(x = calendar_year, y = total_emissions, fill = local_authority)) +
  geom_col() +
  scale_y_continuous(labels = scales::comma) +
  scale_x_continuous(breaks = seq(start_year, max_year, by = 1)) +
  scale_fill_manual(values = weca_palette_4) +
  labs(
    title = "Total territorial emissions (greenhouse gases)",
    subtitle = glue("West of England local authorities, {start_year}-{max_year}"),
    x = "Year",
    y = "KtCO2e", 
    fill = "Local authority",
    caption = "Source: UK local authority and regional greenhouse gas emissions statistics"
  ) +
  coord_flip() +
  theme_weca_bar()

emissions_weca_plot

Show/Hide Code
sector_emissions_weca_max_year_tbl <-
ghg_emissions_tbl |>
  filter(
    local_authority_code %in% weca_ns_la_codes,
    calendar_year == max_year,
  ) |>
  group_by(la_ghg_sector) |>
  summarise(total_emissions_kt_co2e = sum(territorial_emissions_kt_co2e), .groups = "drop") |> 
  mutate(pct = total_emissions_kt_co2e / sum(total_emissions_kt_co2e)) 
Show/Hide Code
sector_emission_proportion_gt <- sector_emissions_weca_max_year_tbl |> 
  gt() |>
  fmt_number(columns = total_emissions_kt_co2e, decimals = 0  ) |>
  fmt_percent(columns = pct, decimals = 0) |>
  cols_label(
    la_ghg_sector = "GHG Sector",
    total_emissions_kt_co2e = "Total emissions (KtCO2e)",
    pct = "Percentage of total"
  ) |>
  tab_header(
    title = "Territorial emissions by GHG sector",
    subtitle = glue("West of England, {max_year}")
  ) |>
  tab_source_note(source_note = "Source: UK local authority and regional greenhouse gas emissions statistics") |>
  tab_options(table.font.size = px(14))

Reuse