TRAN5115M · SESSION 6 & ASSESSMENT BRIEFING
Transport Data Science
Session 6
Coursework Brief
Marking Criteria
Dr Yuanxuan Yang (Yang)
Lecturer in Data Science of Transport · Institute for Transport Studies
AGENDA
TRAN5115M · Transport Data Science · ITS, University of Leeds
What we will cover today
03
Session 6
Joins, models & publishing
Combine spatial and tabular datasets, derive new metrics, and produce a polished Quarto report.
01
Coursework
Data science project report
Final assessed submission. We will walk through the brief: deadline, length, format and structure.
02
Marking Criteria
How marks are awarded
Four weighted categories
Coursework Submission
TRAN5115M · Transport Data Science · ITS, University of Leeds
Submission
Imagine presenting findings to a large organisation — clarity, evidence, and impact
15 May 2026
14:00 deadline
10 pages
max (excl. coversheet & refs, acknowledgements and appendices)
3,000
word maximum (excluding tables, code, references, and captions)
.zip
PDF + .qmd via Minerva (Turnitin)
Can include small data files if needed
Other essentials
Format
Quarto .qmd source + rendered PDF
Size limit
≤ 40 MB for the submitted .zip
AI use
GREEN category — encouraged, but acknowledge it
TRAN5115M · Transport Data Science · ITS, University of Leeds
Report Structure
01
Introduction
Clear research question, context, motivation, link to literature.
02
Input data & cleaning
Datasets described, quality discussed, processing steps documented.
03
Exploratory analysis
Initial visualisations, summary stats, the key patterns you spotted.
04
Analysis & results
Detailed analysis with supporting visualisation and clear presentation.
05
Discussion & Conclusion
Result, key findings, interpretation,
Policy implications/recommendations,
Strengths and limitations,
Future directions.
06
References
Properly formatted; mix academic + technical/policy. Generate via Quarto.
Marking Criteria
Transport data hack for MSc students, Post-Graduates and Staff
Location: ITS room 1.11
Time: 14:00-15:00 and optionally until 17:00 Thursday 7th May
This event is designed to build data, coding and reproducible research skills for ITS staff and students. It is also specifically designed to support ITS MSc students with their dissertation projects by providing a space to ask questions about importing, processing and visualising data.
If you are stuck on any data-related challenges, improve your data analysis, or learn more about data science techniques, this is for you!
Marking Criteria
PART 3 · WEIGHT BREAKDOWN
TRAN5115M · Transport Data Science · ITS, University of Leeds
100%
of final mark
20%
Data processing
20%
Visualisation & report
20%
Code quality, efficiency and reproducibility
40%
Understanding the data science process, including choice of topic and impact
Full details in
https://itsleeds.github.io/tds/marking-criteria.html
TRAN5115M · Transport Data Science · ITS, University of Leeds
Data processing
20%
Visualisation & report
20%
TRAN5115M · Transport Data Science · ITS, University of Leeds
Code quality, efficiency & reproducibility
20%
Understanding the data science process, including choice of topic and impact
40%
Some suggestions
1
Clear research question
A sharp research question makes every later choice easier.
2
Combine, don't dump
Joins and feature engineering are where data turns into evidence.
3
Show, then explain
Your figure/table can do heavy lifting
4
Render before you submit
Catch broken citations, missing figures and overflow early.
5
Reflect on impact
Generalisability and policy relevance lift Merit to Distinction.
SESSION 6
Joins, Models & Publishing
From STATS19 crash points to a polished, reproducible Quarto report.
PART 1 · LEARNING OUTCOMES
4 / 21
TRAN5115M · Transport Data Science · ITS, University of Leeds
By the end of Session 6 you will be able to…
Perform spatial joins
Link points (crashes) to polygons (LSOAs) using sf::st_join().
Use key-based joins
Combine tabular data with dplyr's join family on shared identifiers.
Engineer derived metrics
Move from raw counts to per-capita rates with mutate().
Communicate with Quarto
Produce reproducible, well-cited reports ready for assessment.
PART 1 · DATA ACQUISITION
5 / 21
TRAN5115M · Transport Data Science · ITS, University of Leeds
STATS19 — five years of GB road crash data
Pull, combine, and convert to a spatial object in three short steps
library(tidyverse); library(sf); library(stats19)
# 1. Download multiple years
crashes_2019 = get_stats19(year = 2019, type = "accidents", ask = FALSE)
# … repeat for 2020–2023
# 2. Bind into one tidy frame
# omitted
# 3. Convert to sf (point geometry)
# omitted
# 4. Filter to West Yorkshire
crashes_wy = crashes_sf |> filter(police_force == "West Yorkshire")
1
Pull each year
get_stats19() returns a tibble per year — one call per year keeps memory predictable.
2
Combine flexibly
bind_rows() tolerates schema drift; rbind() requires identical columns.
3
sf points
format_sf() drops rows with missing coordinates and returns an sf object.
4
Scope your study
filter() on police_force narrows the frame for downstream spatial joins.
PART 1 · COMBINING DATA
6 / 21
TRAN5115M · Transport Data Science · ITS, University of Leeds
bind_rows() vs rbind()
When the columns don't quite line up, choose your tool deliberately
Base R
rbind()
Strict
Tidyverse
bind_rows()
Flexible
Use rbind() if you’re sure the data frames have identical structure.
Use bind_rows() for robust and flexible row-binding, especially in pipelines.
PART 1 · SPATIAL JOINS
7 / 21
TRAN5115M · Transport Data Science · ITS, University of Leeds
What is a spatial join?
A join driven by geometry, not by a key column
Combine two spatial datasets based on their geographic relationship — whether one geometry intersects, contains, or lies within another.
Function signature
st_join(x, y, join = st_intersects)
x = primary (e.g. points) · y = reference (e.g. polygons)
Spatial predicates
st_intersects — Any kind of overlap
st_within — x lies fully inside y
st_contains — x fully encloses y
st_touches — Share a boundary, no interior overlap
st_disjoint — No shared geometry at all
Why this matters for transport data science
Map crashes, stops or GPS traces to administrative zones
Enrich observations with population, accessibility or land-use
Aggregate point events into polygon-level summaries
PART 1 · SPATIAL JOIN IN PRACTICE
8 / 21
TRAN5115M · Transport Data Science · ITS, University of Leeds
Linking crash points to LSOA polygons
Each crash gets stamped with the LSOA it falls inside
Crashes (sf)
~thousands of points
LSOAs (sf)
polygons for West Yorkshire
Joined frame
each point + lsoa21cd, lsoa21nm
R
# Each crash inherits the LSOA polygon it falls inside
crashes_in_lsoa = st_join(lsoa_wy, crashes_wy)
# Default predicate is st_intersects — works because crashes are points
Sanity checks: setdiff() to see new columns · is.na(lsoa21cd) to flag unmatched crashes
PART 1 · AGGREGATION
9 / 21
TRAN5115M · Transport Data Science · ITS, University of Leeds
Aggregating crashes by LSOA
From one row per crash to one row per neighbourhood
group_by ▸ summarise
lsoa_crashes_count = crashes_in_lsoa |>
st_drop_geometry() |>
group_by(lsoa21cd) |>
summarise(
fatal_crashes_n = sum(accident_severity == "Fatal"),
serious_crashes_n = sum(accident_severity == "Serious"),
slight_crashes_n = sum(accident_severity == "Slight"),
all_crashes_n = fatal_crashes_n + serious_crashes_n + slight_crashes_n
)
Drop geometry first
Aggregation is tabular — keeping geometry slows it down and isn't needed here.
group key
lsoa21cd uniquely identifies each LSOA; group_by() collapses crashes within each.
Severity breakdown
summarise() with conditional sums gives counts per severity in a single pass.
PART 1 · FEATURE ENGINEERING
11 / 21
TRAN5115M · Transport Data Science · ITS, University of Leeds
From raw counts to meaningful rates
Population-normalised metrics make areas of different sizes comparable
METRIC
crash_pp
all_crashes_n / pop
Raw rate — crashes per resident.
METRIC
crash_per_1000
crash_pp * 1000
Same idea, friendlier scale for mapping and tables.
METRIC
severity_ratio
(fatal_n + serious_n) / all_crashes_n
Where do the most serious outcomes concentrate?
Watch for division by zero
severity_ratio is NaN when all_crashes_n is 0. Replace with 0 explicitly so colour scales don't break.
PART 1 · PUBLISHING WITH QUARTO
13 / 21
TRAN5115M · Transport Data Science · ITS, University of Leeds
Publishing your work with Quarto
Reproducibility is a deliverable — not a side-effect
Citations
Manage references in a .bib file; cite with [@key] and Quarto generates the bibliography automatically.
[@lovelace_stats19_2019]
Cross-references
Label figures with #| label: fig-x and reference them as @fig-x — numbers update on render.
@fig-crash-map · @tbl-summary
Output formats
Same .qmd → HTML, PDF, or revealjs slides. Configure once in the YAML header.
format: [html, pdf]
Callouts & code chunks
Highlight key info with .callout-note / -warning / -tip. Hide noisy code with #| echo: false.
:::{.callout-note} … :::