Title: | Work with Open Road Traffic Casualty Data from Great Britain |
---|---|
Description: | Tools to help download, process and analyse the UK road collision data collected using the 'STATS19' form. The datasets are provided as 'CSV' files with detailed road safety information about the circumstances of car crashes and other incidents on the roads resulting in casualties in Great Britain from 1979 to present. Tables are available on 'colissions' with the circumstances (e.g. speed limit of road), information about 'vehicles' involved (e.g. type of vehicle), and 'casualties' (e.g. age). The statistics relate only to events on public roads that were reported to the police, and subsequently recorded, using the 'STATS19' collision reporting form. See the Department for Transport website <https://www.data.gov.uk/dataset/cb7ae6f0-4be6-4935-9277-47e5ce24a11f/road-safety-data> for more information on these datasets. The package is described in a paper in the Journal of Open Source Software (Lovelace et al. 2019) <doi:10.21105/joss.01181>. See Gilardi et al. (2022) <doi:10.1111/rssa.12823>, Vidal-Tortosa et al. (2021) <doi:10.1016/j.jth.2021.101291>, and Tait et al. (2023) <doi:10.1016/j.aap.2022.106895> for examples of how the data can be used for methodological and empirical road safety research. |
Authors: | Robin Lovelace [aut, cre] , Malcolm Morgan [aut] , Layik Hama [aut] , Mark Padgham [aut] , David Ranzolin [rev], Adam Sparks [rev, ctb] , Ivo Wengraf [ctb], RAC Foundation [fnd] |
Maintainer: | Robin Lovelace <[email protected]> |
License: | GPL-3 |
Version: | 3.2.0 |
Built: | 2024-11-27 04:11:28 UTC |
Source: | https://github.com/ropensci/stats19 |
Sample of stats19 data (2022 collisions)
A data frame
These were generated using the script in the
data-raw
directory (misc.Rmd
file).
nrow(accidents_sample_raw) accidents_sample_raw
nrow(accidents_sample_raw) accidents_sample_raw
Sample of stats19 data (2022 casualties)
A data frame
These were generated using the script in the
data-raw
directory (misc.Rmd
file).
nrow(casualties_sample_raw) casualties_sample_raw
nrow(casualties_sample_raw) casualties_sample_raw
Local helper to be reused.
check_input_file(filename = NULL, type = NULL, data_dir = NULL, year = NULL)
check_input_file(filename = NULL, type = NULL, data_dir = NULL, year = NULL)
filename |
Character string of the filename of the .csv to read, if this is given, type and years determine whether there is a target to read, otherwise disk scan would be needed. |
type |
The type of file to be downloaded (e.g. 'collisions', 'casualty' or 'vehicles'). Not case sensitive and searches using regular expressions ('acc' will work). |
data_dir |
Where sets of downloaded data would be found. |
year |
Single year for which data are to be read |
Download STATS19 data for a year
dl_stats19( year = NULL, type = NULL, data_dir = get_data_directory(), file_name = NULL, ask = FALSE, silent = FALSE, timeout = 600 )
dl_stats19( year = NULL, type = NULL, data_dir = get_data_directory(), file_name = NULL, ask = FALSE, silent = FALSE, timeout = 600 )
year |
A year matching file names on the STATS19
data release page
e.g. |
type |
One of 'collision', 'casualty', 'Vehicle'; defaults to 'collision'. This text string is used to match the file names released by the DfT. |
data_dir |
Parent directory for all downloaded files. Defaults to |
file_name |
The file name (DfT named) to download. |
ask |
Should you be asked whether or not to download the files? |
silent |
Boolean. If |
timeout |
Timeout in seconds for the download if current option is less than this value. Defaults to 600 (10 minutes). |
This function downloads and unzips UK road crash data.
It results in unzipped .csv files that are put
in the temporary directory specified by get_data_directory()
or provided data_dir
.
The file downloaded would be for a specific year (e.g. 2022). It could also be a file containing data for a range of two (e.g. 2005-2014).
The dl_*
functions can download many MB of data so ensure you
have a sufficient internet access and hard disk space.
if (curl::has_internet()) { # type by default is collisions table dl_stats19(year = 2022) # with type as casualty dl_stats19(year = 2022, type = "casualty") # try another year dl_stats19(year = 2018) }
if (curl::has_internet()) { # type by default is collisions table dl_stats19(year = 2022) # with type as casualty dl_stats19(year = 2022, type = "casualty") # try another year dl_stats19(year = 2018) }
URL decoded file names. Currently there are 52 file names released by the DfT (Department for Transport) and the details include how these were obtained and would be kept up to date.
A named list
These were generated using the script in the
data-raw
directory (misc.Rmd
file).
head(file_names)
head(file_names)
Currently, there are 52 file names to download/read data from.
find_file_name(years = NULL, type = NULL)
find_file_name(years = NULL, type = NULL)
years |
Year for which data are to be found |
type |
One of 'collisions', 'casualty' or 'vehicles' ignores case. |
find_file_name(2016) find_file_name(2016, type = "collision") find_file_name(1985, type = "collision") find_file_name(type = "cas") find_file_name(type = "collision") find_file_name(2016:2022) # warning when multiple years requested
find_file_name(2016) find_file_name(2016, type = "collision") find_file_name(1985, type = "collision") find_file_name(type = "cas") find_file_name(type = "collision") find_file_name(2016:2022) # warning when multiple years requested
Format STATS19 casualties
format_casualties(x)
format_casualties(x)
x |
Data frame created with |
This function formats raw STATS19 data
if(curl::has_internet()) { dl_stats19(year = 2022, type = "casualty") x = read_casualties(year = 2022) casualties = format_casualties(x) }
if(curl::has_internet()) { dl_stats19(year = 2022, type = "casualty") x = read_casualties(year = 2022) casualties = format_casualties(x) }
Format STATS19 'collisions' data
format_collisions(x)
format_collisions(x)
x |
Data frame created with |
This is a helper function to format raw STATS19 data
if(curl::has_internet()) { dl_stats19(year = 2022, type = "collision") x = read_collisions(year = 2022, format = FALSE) x = readr::read_csv("https://github.com/ropensci/stats19/releases/download/v3.0.0/fatalities.csv") if(nrow(x) > 0) { x[1:3, 1:12] crashes = format_collisions(x) crashes[1:3, 1:12] summary(crashes$datetime) } }
if(curl::has_internet()) { dl_stats19(year = 2022, type = "collision") x = read_collisions(year = 2022, format = FALSE) x = readr::read_csv("https://github.com/ropensci/stats19/releases/download/v3.0.0/fatalities.csv") if(nrow(x) > 0) { x[1:3, 1:12] crashes = format_collisions(x) crashes[1:3, 1:12] summary(crashes$datetime) } }
This function takes messy column names and returns clean ones that work well with
R by default. Names that are all lower case with no R-unfriendly characters
such as spaces and -
are returned.
format_column_names(column_names)
format_column_names(column_names)
column_names |
Column names to be cleaned |
Column names cleaned.
if(curl::has_internet()) { crashes_raw = read_collisions(year = 2022) column_names = names(crashes_raw) column_names format_column_names(column_names = column_names) }
if(curl::has_internet()) { crashes_raw = read_collisions(year = 2022) column_names = names(crashes_raw) column_names format_column_names(column_names = column_names) }
This function is a wrapper around the spatstat.geom::ppp()
function and
it is used to transform STATS19 data into a ppp format.
format_ppp(data, window = NULL, ...)
format_ppp(data, window = NULL, ...)
data |
A STATS19 dataframe to be converted into ppp format. |
window |
A windows of observation, an object of class |
... |
Additional parameters that should be passed to
|
A ppp object.
format_sf
for an analogous function used to convert
data into sf format and spatstat.geom::ppp()
for the original function.
if (requireNamespace("spatstat.geom", quietly = TRUE)) { x_ppp = format_ppp(accidents_sample) x_ppp }
if (requireNamespace("spatstat.geom", quietly = TRUE)) { x_ppp = format_ppp(accidents_sample) x_ppp }
Format convert STATS19 data into spatial (sf) object
format_sf(x, lonlat = FALSE)
format_sf(x, lonlat = FALSE)
x |
Data frame created with |
lonlat |
Should the results be returned in longitude/latitude?
By default |
x_sf = format_sf(accidents_sample) sf:::plot.sf(x_sf)
x_sf = format_sf(accidents_sample) sf:::plot.sf(x_sf)
Format STATS19 vehicles data
format_vehicles(x)
format_vehicles(x)
x |
Data frame created with |
This function formats raw STATS19 data
if(curl::has_internet()) { dl_stats19(year = 2022, type = "vehicle", ask = FALSE) x = read_vehicles(year = 2022, format = FALSE) vehicles = format_vehicles(x) }
if(curl::has_internet()) { dl_stats19(year = 2022, type = "vehicle", ask = FALSE) x = read_vehicles(year = 2022, format = FALSE) vehicles = format_vehicles(x) }
Get data download dir
get_data_directory()
get_data_directory()
# get_data_directory()
# get_data_directory()
Download vehicle data from the DVSA MOT API using VRM.
get_MOT(vrm, apikey)
get_MOT(vrm, apikey)
vrm |
A list of VRMs as character strings. |
apikey |
Your API key as a character string. |
This function takes a a character vector of vehicle registrations (VRMs) and returns vehicle data from MOT records. It returns a data frame of those VRMs which were successfully used with the DVSA MOT API.
Information on the DVSA MOT API is available here: https://dvsa.github.io/mot-history-api-documentation/
The DVSA MOT API requires a registration. The function therefore requires the API key provided by the DVSA. Be aware that the API has usage limits. The function will therefore limit lists with more than 150,000 VRMs.
vrm = c("1RAC","P1RAC") apikey = Sys.getenv("MOTKEY") if(nchar(apikey) > 0) { get_MOT(vrm = vrm, apikey = apikey) }
vrm = c("1RAC","P1RAC") apikey = Sys.getenv("MOTKEY") if(nchar(apikey) > 0) { get_MOT(vrm = vrm, apikey = apikey) }
Download, read and format STATS19 data in one function.
get_stats19( year = NULL, type = "collision", data_dir = get_data_directory(), file_name = NULL, format = TRUE, ask = FALSE, silent = FALSE, output_format = "tibble", ... )
get_stats19( year = NULL, type = "collision", data_dir = get_data_directory(), file_name = NULL, format = TRUE, ask = FALSE, silent = FALSE, output_format = "tibble", ... )
year |
A year matching file names on the STATS19
data release page
e.g. |
type |
One of 'collision', 'casualty', 'Vehicle'; defaults to 'collision'. This text string is used to match the file names released by the DfT. |
data_dir |
Parent directory for all downloaded files. Defaults to |
file_name |
The file name (DfT named) to download. |
format |
Switch to return raw read from file, default is |
ask |
Should you be asked whether or not to download the files? |
silent |
Boolean. If |
output_format |
A string that specifies the desired output format. The
default value is |
... |
Other arguments be passed to |
This function uses gets STATS19 data. Behind the scenes it uses
dl_stats19()
and read_*
functions, returning a
tibble
(default), data.frame
, sf
or ppp
object, depending on the
output_format
parameter.
The function returns data for a specific year (e.g. year = 2022
)
Note: for years before 2016 the function may return data from more years than are requested due to the nature of the files hosted at data.gov.uk.
As this function uses dl_stats19
function, it can download many MB of data,
so ensure you have a sufficient disk space.
If output_format = "data.frame"
or output_format = "sf"
or output_format = "ppp"
then the output data is transformed into a data.frame, sf or ppp
object using the as.data.frame()
or format_sf()
or format_ppp()
functions, as shown in the examples.
if(curl::has_internet()) { x = get_stats19(2022, silent = TRUE, format = TRUE) class(x) # data.frame output x = get_stats19(2022, silent = TRUE, output_format = "data.frame") class(x) # Run tests only if endpoint is alive: if(nrow(x) > 0) { # sf output x_sf = get_stats19(2022, silent = TRUE, output_format = "sf") # sf output with lonlat coordinates x_sf = get_stats19(2022, silent = TRUE, output_format = "sf", lonlat = TRUE) sf::st_crs(x_sf) if (requireNamespace("spatstat.geom", quietly = TRUE)) { # ppp output x_ppp = get_stats19(2022, silent = TRUE, output_format = "ppp") # We can use the window parameter of format_ppp function to filter only the # events occurred in a specific area. For example we can create a new bbox # of 5km around the city center of Leeds leeds_window = spatstat.geom::owin( xrange = c(425046.1, 435046.1), yrange = c(428577.2, 438577.2) ) leeds_ppp = get_stats19(2022, silent = TRUE, output_format = "ppp", window = leeds_window) spatstat.geom::plot.ppp(leeds_ppp, use.marks = FALSE, clipwin = leeds_window) # or even more fancy examples where we subset all the events occurred in a # pre-defined polygon area # The following example requires osmdata package # greater_london_sf_polygon = osmdata::getbb( # "Greater London, UK", # format_out = "sf_polygon" # ) # spatstat works only with planar coordinates # greater_london_sf_polygon = sf::st_transform(greater_london_sf_polygon, 27700) # then we extract the coordinates and create the window object. # greater_london_polygon = sf::st_coordinates(greater_london_sf_polygon)[, c(1, 2)] # greater_london_window = spatstat.geom::owin(poly = greater_london_polygon) # greater_london_ppp = get_stats19(2022, output_format = "ppp", window = greater_london_window) # spatstat.geom::plot.ppp(greater_london_ppp, use.marks = FALSE, clipwin = greater_london_window) } } }
if(curl::has_internet()) { x = get_stats19(2022, silent = TRUE, format = TRUE) class(x) # data.frame output x = get_stats19(2022, silent = TRUE, output_format = "data.frame") class(x) # Run tests only if endpoint is alive: if(nrow(x) > 0) { # sf output x_sf = get_stats19(2022, silent = TRUE, output_format = "sf") # sf output with lonlat coordinates x_sf = get_stats19(2022, silent = TRUE, output_format = "sf", lonlat = TRUE) sf::st_crs(x_sf) if (requireNamespace("spatstat.geom", quietly = TRUE)) { # ppp output x_ppp = get_stats19(2022, silent = TRUE, output_format = "ppp") # We can use the window parameter of format_ppp function to filter only the # events occurred in a specific area. For example we can create a new bbox # of 5km around the city center of Leeds leeds_window = spatstat.geom::owin( xrange = c(425046.1, 435046.1), yrange = c(428577.2, 438577.2) ) leeds_ppp = get_stats19(2022, silent = TRUE, output_format = "ppp", window = leeds_window) spatstat.geom::plot.ppp(leeds_ppp, use.marks = FALSE, clipwin = leeds_window) # or even more fancy examples where we subset all the events occurred in a # pre-defined polygon area # The following example requires osmdata package # greater_london_sf_polygon = osmdata::getbb( # "Greater London, UK", # format_out = "sf_polygon" # ) # spatstat works only with planar coordinates # greater_london_sf_polygon = sf::st_transform(greater_london_sf_polygon, 27700) # then we extract the coordinates and create the window object. # greater_london_polygon = sf::st_coordinates(greater_london_sf_polygon)[, c(1, 2)] # greater_london_window = spatstat.geom::owin(poly = greater_london_polygon) # greater_london_ppp = get_stats19(2022, output_format = "ppp", window = greater_london_window) # spatstat.geom::plot.ppp(greater_london_ppp, use.marks = FALSE, clipwin = greater_london_window) } } }
See the DfT's documentation on adjustment factors Annex: Update to severity adjustments methodology.
get_stats19_adjustments( data_dir = get_data_directory(), u = paste0("https://data.dft.gov.uk/road-accidents-safety-data/", "dft-road-casualty-statistics-casualty-adjustment-lookup_", "2004-latest-published-year.csv") )
get_stats19_adjustments( data_dir = get_data_directory(), u = paste0("https://data.dft.gov.uk/road-accidents-safety-data/", "dft-road-casualty-statistics-casualty-adjustment-lookup_", "2004-latest-published-year.csv") )
data_dir |
Where sets of downloaded data would be found. |
u |
The URL of the zip file with adjustments to download |
See Estimating and adjusting for changes in the method of severity reporting for road accidents and casualty data: final report for details.
if(curl::has_internet()) { adjustment = get_stats19_adjustments() }
if(curl::has_internet()) { adjustment = get_stats19_adjustments() }
Download DVLA-based vehicle data from the TfL API using VRM.
get_ULEZ(vrm)
get_ULEZ(vrm)
vrm |
A list of VRMs as character strings. |
This function takes a character vector of vehicle registrations (VRMs) and returns DVLA-based vehicle data from TfL's API, included ULEZ eligibility. It returns a data frame of those VRMs which were successfully used with the TfL API. Vehicles are either compliant, non-compliant or exempt. ULEZ-exempt vehicles will not have all vehicle details returned - they will simply be marked "exempt".
Be aware that the API has usage limits. The function will therefore limit API calls to below 50 per minute - this is the maximum rate before an API key is required.
if(curl::has_internet()) { vrm = c("1RAC","P1RAC") get_ULEZ(vrm = vrm) }
if(curl::has_internet()) { vrm = c("1RAC","P1RAC") get_ULEZ(vrm = vrm) }
Convert file names to urls
get_url( file_name = "", domain = "https://data.dft.gov.uk", directory = "road-accidents-safety-data" )
get_url( file_name = "", domain = "https://data.dft.gov.uk", directory = "road-accidents-safety-data" )
file_name |
Optional file name to add to the url returned (empty by default) |
domain |
The domain from where the data will be downloaded |
directory |
The subdirectory of the url |
This function returns urls that allow data to be downloaded from the pages:
https://data.dft.gov.uk/road-accidents-safety-data/RoadSafetyData_2015.zip
Last updated: October 2020.
Files available from the s3 url in the default domain
argument.
# get_url(find_file_name(1985))
# get_url(find_file_name(1985))
Helper function to locate files. Given below params, the function returns 0 or more files found at location/names given.
locate_files( data_dir = get_data_directory(), type = NULL, years = NULL, quiet = FALSE )
locate_files( data_dir = get_data_directory(), type = NULL, years = NULL, quiet = FALSE )
data_dir |
Super directory where dataset(s) were first downloaded to. |
type |
One of 'Collision', 'Casualties', 'Vehicles'; defaults to 'Collision', ignores case. |
years |
Years for which data are to be found |
quiet |
Print out messages (files found) |
Character string representing the full path of a single file found, list of directories where data from the Department for Transport (stats19::filenames) have been downloaded, or NULL if no files were found.
Pin down a file on disk from four parameters.
locate_one_file( filename = NULL, data_dir = get_data_directory(), year = NULL, type = NULL )
locate_one_file( filename = NULL, data_dir = get_data_directory(), year = NULL, type = NULL )
filename |
Character string of the filename of the .csv to read, if this is given, type and years determine whether there is a target to read, otherwise disk scan would be needed. |
data_dir |
Where sets of downloaded data would be found. |
year |
Single year for which file is to be found. |
type |
One of: 'Collision', 'Casualties', 'Vehicles'; ignores case. |
One of: path for one file, a message More than one file found
or error if none found.
locate_one_file() locate_one_file(filename = "Cas.csv")
locate_one_file() locate_one_file(filename = "Cas.csv")
Generate a phrase for data download purposes
phrase()
phrase()
stats19:::phrase()
stats19:::phrase()
This dataset represents the 43 police forces in England and Wales. These are described on the Wikipedia page. on UK police forces.
An sf data frame
The geographic boundary data were taken from the UK government's official geographic data portal. See http://geoportal.statistics.gov.uk/
These were generated using the script in the
data-raw
directory (misc.Rmd
file) in the package's GitHub repo:
github.com/ITSLeeds/stats19.
nrow(police_boundaries) police_boundaries[police_boundaries$pfa16nm == "West Yorkshire", ] sf:::plot.sf(police_boundaries)
nrow(police_boundaries) police_boundaries[police_boundaries$pfa16nm == "West Yorkshire", ] sf:::plot.sf(police_boundaries)
Read in STATS19 road safety data from .csv files downloaded.
read_casualties( year = NULL, filename = "", data_dir = get_data_directory(), format = TRUE )
read_casualties( year = NULL, filename = "", data_dir = get_data_directory(), format = TRUE )
year |
Single year for which data are to be read |
filename |
Character string of the filename of the .csv to read, if this is given, type and years determine whether there is a target to read, otherwise disk scan would be needed. |
data_dir |
Where sets of downloaded data would be found. |
format |
Switch to return raw read from file, default is |
The function returns a data frame, in which each record is a reported casualty in the STATS19 dataset.
if(curl::has_internet()) { dl_stats19(year = 2022, type = "casualty") casualties = read_casualties(year = 2022) }
if(curl::has_internet()) { dl_stats19(year = 2022, type = "casualty") casualties = read_casualties(year = 2022) }
Read in STATS19 road safety data from .csv files downloaded.
read_collisions( year = NULL, filename = "", data_dir = get_data_directory(), format = TRUE, silent = FALSE )
read_collisions( year = NULL, filename = "", data_dir = get_data_directory(), format = TRUE, silent = FALSE )
year |
Single year for which data are to be read |
filename |
Character string of the filename of the .csv to read, if this is given, type and years determine whether there is a target to read, otherwise disk scan would be needed. |
data_dir |
Where sets of downloaded data would be found. |
format |
Switch to return raw read from file, default is |
silent |
Boolean. If |
This is a wrapper function to access and load stats 19 data in a user-friendly way. The function returns a data frame, in which each record is a reported incident in the STATS19 data.
if(curl::has_internet()) { dl_stats19(year = 2019, type = "collision") ac = read_collisions(year = 2019) dl_stats19(year = 2019, type = "collision") ac_2019 = read_collisions(year = 2019) }
if(curl::has_internet()) { dl_stats19(year = 2019, type = "collision") ac = read_collisions(year = 2019) dl_stats19(year = 2019, type = "collision") ac_2019 = read_collisions(year = 2019) }
Read in stats19 road safety data from .csv files downloaded.
read_vehicles( year = NULL, filename = "", data_dir = get_data_directory(), format = TRUE )
read_vehicles( year = NULL, filename = "", data_dir = get_data_directory(), format = TRUE )
year |
Single year for which data are to be read |
filename |
Character string of the filename of the .csv to read, if this is given, type and years determine whether there is a target to read, otherwise disk scan would be needed. |
data_dir |
Where sets of downloaded data would be found. |
format |
Switch to return raw read from file, default is |
The function returns a data frame, in which each record is a reported vehicle in the STATS19 dataset for the data_dir and filename provided.
if(curl::has_internet()) { dl_stats19(year = 2019, type = "vehicle") ve = read_vehicles(year = 2019) }
if(curl::has_internet()) { dl_stats19(year = 2019, type = "vehicle") ve = read_vehicles(year = 2019) }
Interactively select from options
select_file(fnames)
select_file(fnames)
fnames |
File names to select from |
# fnames = c("f1", "f2") # stats19:::select_file(fnames)
# fnames = c("f1", "f2") # stats19:::select_file(fnames)
Handy function to manage stats19
package underlying environment
variable. If run interactively it makes sure user does not change
directory by mistatke.
set_data_directory(data_path)
set_data_directory(data_path)
data_path |
valid existing path to save downloaded files in. |
# set_data_directory("MY_PATH")
# set_data_directory("MY_PATH")
stats19_schema
and stats19_variables
contain
metadata on stats19 data.
stats19_schema
is a look-up table matching
codes provided in the raw stats19 dataset with
character strings.
The schema data can be (re-)generated using the script in the
data-raw
directory.
Sample of stats19 data (2022 vehicles)
A data frame
These were generated using the script in the
data-raw
directory (misc.Rmd
file).
nrow(vehicles_sample_raw) vehicles_sample_raw
nrow(vehicles_sample_raw) vehicles_sample_raw