stats19reports

Reproducible road safety reports for Great Britain from STATS19 data

R
road safety
STATS19
open data
An R package that builds parameterised Local Authority, parish and national road safety reports from DfT STATS19 collision data — including geography, deprivation, costs and OpenStreetMap network analysis.
Published

August 8, 2026

Overview

stats19reports is an R package that automates the production of reproducible road safety reports for any area in Great Britain, built on top of the rOpenSci stats19 package. A full Local Authority report that would previously take days of manual data wrangling runs in a single command; individual sections can be updated and re-rendered without re-running the whole pipeline.

The package produces three types of report:

  • Local Authority reports — comprehensive analysis for any GB Local Authority, matched by name against the ONS boundary files
  • Parish council reports — the same framework scaled down to parish boundaries, with a longer default analysis period to compensate for small numbers
  • National pavement reports — a GB-wide study of pedestrians struck on a footway or verge, with BBC-styled charts and treemaps of where fatalities happen
# install
remotes::install_github("ActiveAnalytics-nl/stats19reports")

What the reports cover

Each Local Authority report works through the following sections, each independently cached so re-runs are fast:

Section What it covers
Rankings LA’s position among all 206 GB authorities for fatal, KSI, serious and slight casualties — overall, cyclists and pedestrians
National maps Choropleth grids of LA casualty rates across GB
Road network Casualties matched to OpenStreetMap links; sortable table of top roads by collision count
Speed limits Casualty and collision rates per km of road by speed limit category
Crash conditions Bar charts by road surface, junction type, lighting, weather
LSOA / IMD Population and casualty distribution by Lower Super Output Area and Index of Multiple Deprivation decile
MSOA National casualty ranking for each MSOA in the LA; IMD scatter plots for the strongest deprivation-casualty correlations
Demographics Casualties by age band and sex; KSI breakdown
Pavement collisions Single-vehicle pavement collisions: waffle chart coloured by striking vehicle
Costs DfT TAG / RAS4001 collision cost valuation by severity and road type

Parish reports share the same engine but use parish boundaries from the national planning data platform and extend back to 2010 by default — necessary because small areas accumulate few collisions per year.


Usage

Local Authority report

library(stats19reports)

# full build — sections are cached, so interrupted runs resume
build_la_report_data("Bristol", base_year = 2021, upper_year = 2025)
render_la_report("Bristol")

Iterating on one section

# after changing something in the MSOA analysis:
devtools::load_all()
build_la_report_data("Bristol", sections = "msoa", overwrite = TRUE)
render_la_report("Bristol")

Parish council report

build_parish_report_data("Winsley")
render_parish_report("Winsley")

National pavement report

build_pavement_report_data(base_year = 2021, upper_year = 2025)

How the pipeline works

The pipeline is split into named sections that correspond to parts of the rendered report. Each section saves its outputs to outputs/<area>/data/sections/<name>.rds and is skipped on subsequent runs if that file already exists. Shared downloads — STATS19 data, LA boundaries and the IMD 2025 GeoPackage — are cached separately so they are fetched only once regardless of how many sections are (re-)run.

# see the section → report part mapping
report_sections()
#>       rankings       national    interactive            osm
#> "Introduction…" "Intro: maps…" "Where in LA?" "Road network…"
#>     conditions          lsoa          msoa   demographics
#> "Conditions…"   "LSOA/IMD…"    "MSOA…"      "Demographics…"
#>     pavements         costs
#> "Pavements…"    "Costs…"

The design is deliberately compatible with the targets R package for projects that need full dependency tracking across multiple LAs — the internal sec_* functions map onto targets almost one-to-one.


Data sources

All data is downloaded programmatically at run time — no manual data preparation is required.

  • STATS19 collision, casualty and vehicle data via the stats19 rOpenSci package
  • Local Authority and LSOA 2021 boundaries from ONS Open Geography Portal
  • MSOA 2021 boundaries and House of Commons MSOA names lookup
  • IMD 2025 LSOA-level Index of Multiple Deprivation
  • LSOA population from ONS mid-year estimates
  • OpenStreetMap driving network via osmactive
  • DfT TAG / RAS4001 value of prevention costs (ODS download)
  • Parish boundaries from planning.data.gov.uk (parish reports)

Technical approach

The package is built around a few design principles that make it practical to use in a production context:

Reproducibility — every output is derived from publicly available open data through documented, version-controlled code. The Quarto report template uses parameters rather than find-and-replace text substitution; all summary statistics and inline prose are generated by package functions rather than embedded in the template.

Incremental builds — slow sections (OSM network download, national choropleth maps, per-street maps) only run once. The OSM driving network is cached separately and shared between the road network and interactive map sections.

Separation of concerns — the report template is thin: it reads an RDS produced by the pipeline and calls helper functions. The prose helpers (la_summary_paragraph(), five_year_sentence(), change_phrase()) and table builders (tabulate_osm_roads(), tabulate_msoa_ranks() etc.) live in the package, so they can be tested and reused independently.

Open source — MIT licensed, available on GitHub. All dependencies are open source; the package avoids any proprietary data sources.


Installation and dependencies

remotes::install_github("activeanalytics-nl/stats19reports")

Key dependencies installed automatically: stats19, sf, tmap (≥ 4.0), osmactive, ggplot2, gt, reactable, openair, readODS, waffle. The national pavement report additionally requires bbplot (remotes::install_github("bbc/bbplot")). The magick package (optional) enables the stitched multi-panel figures.

Full source: github.com/activeanalytics-nl/stats19reports

Back to top