bolster.data_sources.psni.road_traffic_collisions

PSNI Road Traffic Collision Statistics.

Provides access to police-recorded injury road traffic collision (RTC) statistics for Northern Ireland.

Data includes: - Collision records with date, location, road conditions, severity - Casualty records with age, gender, severity, road user class - Vehicle records with type, manoeuvre, driver details - Geographic breakdown by 11 policing districts (aligned with LGDs) - Historical time series from 2013 onwards

Data Source:

Primary Source: OpenDataNI - Police Recorded Injury Road Traffic Collision Statistics

https://www.opendatani.gov.uk/dataset?q=road+traffic+collision

PSNI collects RTC statistics in accordance with STATS20 guidance from the Department for Transport. Data covers injury collisions only (not damage-only). Published under the Open Government Licence v3.0.

PSNI Official Statistics: https://www.psni.police.uk/about-us/our-publications-and-reports/official-statistics/road-traffic-collision-statistics

Update Frequency: Annual (data available ~6 months after year end) Geographic Coverage: Northern Ireland (11 policing districts) Reference Date: Date of collision occurrence Time Coverage: 2013 to present

Example

>>> from bolster.data_sources.psni import road_traffic_collisions
>>> df = road_traffic_collisions.get_collisions()
>>> 'severity' in road_traffic_collisions.get_casualties().columns
True
>>> summary = road_traffic_collisions.get_annual_summary()
>>> 'year' in summary.columns
True

Attributes

logger

OPENDATANI_API

DISTRICT_CODES

DISTRICT_NAMES_TO_CODES

SEVERITY_CODES

CASUALTY_CLASS_CODES

VEHICLE_TYPE_CODES

DAY_OF_WEEK_CODES

LIGHT_CONDITIONS_CODES

WEATHER_CODES

ROAD_SURFACE_CODES

Functions

get_available_years()

Get list of years with available RTC data.

get_collisions([year, force_refresh, decode_values])

Get collision records for a specific year.

get_casualties([year, force_refresh, decode_values])

Get casualty records for a specific year.

get_vehicles([year, force_refresh, decode_values])

Get vehicle records for a specific year.

get_casualties_with_collision_details([year, ...])

Get casualty records merged with collision details.

get_annual_summary([years, force_refresh])

Get annual summary statistics across multiple years.

get_casualties_by_district([year, force_refresh])

Get casualty counts by policing district.

get_casualties_by_road_user([year, force_refresh])

Get casualty counts by road user type.

validate_data(df, data_type)

Validate RTC data integrity.

Module Contents

bolster.data_sources.psni.road_traffic_collisions.logger[source]
bolster.data_sources.psni.road_traffic_collisions.OPENDATANI_API = 'https://admin.opendatani.gov.uk/api/3/action'[source]
bolster.data_sources.psni.road_traffic_collisions.DISTRICT_CODES[source]
bolster.data_sources.psni.road_traffic_collisions.DISTRICT_NAMES_TO_CODES[source]
bolster.data_sources.psni.road_traffic_collisions.SEVERITY_CODES[source]
bolster.data_sources.psni.road_traffic_collisions.CASUALTY_CLASS_CODES[source]
bolster.data_sources.psni.road_traffic_collisions.VEHICLE_TYPE_CODES[source]
bolster.data_sources.psni.road_traffic_collisions.DAY_OF_WEEK_CODES[source]
bolster.data_sources.psni.road_traffic_collisions.LIGHT_CONDITIONS_CODES[source]
bolster.data_sources.psni.road_traffic_collisions.WEATHER_CODES[source]
bolster.data_sources.psni.road_traffic_collisions.ROAD_SURFACE_CODES[source]
bolster.data_sources.psni.road_traffic_collisions.get_available_years()[source]

Get list of years with available RTC data.

Returns:

List of years (integers) in descending order

Return type:

list[int]

Example

>>> years = get_available_years()
>>> len(years) > 0
True
bolster.data_sources.psni.road_traffic_collisions.get_collisions(year=None, force_refresh=False, decode_values=True)[source]

Get collision records for a specific year.

Each row represents a single road traffic collision with details about date, time, location, road conditions, and severity.

Parameters:
  • year (int | None) – Year to fetch (default: latest available)

  • force_refresh (bool) – If True, bypass cache and re-download

  • decode_values (bool) – If True, decode coded values to human-readable strings

Returns:

  • year: int

  • ref: int (collision reference number)

  • district: str (policing district name if decoded)

  • district_code: str (original code)

  • month: int

  • day: int

  • weekday: str (day name if decoded)

  • hour: int

  • vehicles: int (number of vehicles)

  • casualties: int (number of casualties)

  • light_conditions: str (if decoded)

  • weather: str (if decoded)

  • road_surface: str (if decoded)

  • lgd_code: str (ONS LGD code)

  • nuts3_code: str (NUTS3 region code)

Return type:

DataFrame with columns including

Example

>>> df = get_collisions(2024)
>>> 'severity' in df.columns or 'district' in df.columns
True
bolster.data_sources.psni.road_traffic_collisions.get_casualties(year=None, force_refresh=False, decode_values=True)[source]

Get casualty records for a specific year.

Each row represents a single casualty involved in a road traffic collision. Casualties are linked to collisions via the ‘ref’ column.

Parameters:
  • year (int | None) – Year to fetch (default: latest available)

  • force_refresh (bool) – If True, bypass cache and re-download

  • decode_values (bool) – If True, decode coded values to human-readable strings

Returns:

  • year: int

  • ref: int (collision reference number for linking)

  • vehicle_id: int

  • casualty_id: int

  • casualty_class: str (road user type if decoded)

  • sex_code: int

  • age_group: int

  • severity: str (‘Fatal’, ‘Serious’, ‘Slight’ if decoded)

  • severity_code: int (1=fatal, 2=serious, 3=slight)

Return type:

DataFrame with columns including

Example

>>> df = get_casualties(2024)
>>> 'severity' in df.columns
True
bolster.data_sources.psni.road_traffic_collisions.get_vehicles(year=None, force_refresh=False, decode_values=True)[source]

Get vehicle records for a specific year.

Each row represents a single vehicle involved in a road traffic collision. Vehicles are linked to collisions via the ‘ref’ column.

Parameters:
  • year (int | None) – Year to fetch (default: latest available)

  • force_refresh (bool) – If True, bypass cache and re-download

  • decode_values (bool) – If True, decode coded values to human-readable strings

Returns:

  • year: int

  • ref: int (collision reference number for linking)

  • vehicle_id: int

  • vehicle_type: str (if decoded)

  • vehicle_type_code: int

  • driver_sex_code: int

  • driver_age_group: int

Return type:

DataFrame with columns including

Example

>>> df = get_vehicles(2024)
>>> 'vehicle_id' in df.columns
True
bolster.data_sources.psni.road_traffic_collisions.get_casualties_with_collision_details(year=None, force_refresh=False)[source]

Get casualty records merged with collision details.

Combines casualty data with collision information including date, location, and road conditions.

Parameters:
  • year (int | None) – Year to fetch (default: latest available)

  • force_refresh (bool) – If True, bypass cache and re-download

Returns:

DataFrame with casualty records enriched with collision details

Return type:

pandas.DataFrame

Example

>>> df = get_casualties_with_collision_details(2024)
>>> 'severity' in df.columns
True
bolster.data_sources.psni.road_traffic_collisions.get_annual_summary(years=None, force_refresh=False)[source]

Get annual summary statistics across multiple years.

Provides aggregated collision and casualty counts by year, useful for trend analysis.

Parameters:
  • years (list[int] | None) – List of years to include (default: all available)

  • force_refresh (bool) – If True, bypass cache and re-download

Returns:

  • year: int

  • collisions: int (total collisions)

  • casualties: int (total casualties)

  • fatal: int (fatal casualties)

  • serious: int (serious injuries)

  • slight: int (slight injuries)

  • fatalities_per_100_collisions: float

Return type:

DataFrame with columns

Example

>>> summary = get_annual_summary()
>>> 'fatal' in summary.columns
True
bolster.data_sources.psni.road_traffic_collisions.get_casualties_by_district(year=None, force_refresh=False)[source]

Get casualty counts by policing district.

Parameters:
  • year (int | None) – Year to fetch (default: latest available)

  • force_refresh (bool) – If True, bypass cache and re-download

Returns:

  • district: str (policing district name)

  • lgd_code: str (ONS LGD code)

  • collisions: int

  • casualties: int

  • fatal: int

  • serious: int

  • slight: int

Return type:

DataFrame with columns

Example

>>> by_district = get_casualties_by_district(2024)
>>> 'district' in by_district.columns
True
bolster.data_sources.psni.road_traffic_collisions.get_casualties_by_road_user(year=None, force_refresh=False)[source]

Get casualty counts by road user type.

Parameters:
  • year (int | None) – Year to fetch (default: latest available)

  • force_refresh (bool) – If True, bypass cache and re-download

Returns:

  • casualty_class: str (road user type)

  • casualties: int

  • fatal: int

  • serious: int

  • slight: int

  • fatality_rate: float (fatal / total %)

Return type:

DataFrame with columns

Example

>>> by_user = get_casualties_by_road_user(2024)
>>> 'casualty_class' in by_user.columns
True
bolster.data_sources.psni.road_traffic_collisions.validate_data(df, data_type)[source]

Validate RTC data integrity.

Parameters:
  • df (pandas.DataFrame) – DataFrame to validate

  • data_type (Literal['collision', 'casualty', 'vehicle']) – Type of data (‘collision’, ‘casualty’, or ‘vehicle’)

Returns:

True if validation passes

Raises:

PSNIValidationError – If validation fails

Return type:

bool