This document shows you how to map road collisions interactively using the Leaflet package for R.
STATS19 collision data for Greater London during 2014 were downloaded from Transport for London’s Road Safety website. Ward boundary spatial data files were obtained from the London Datastore and converted from shapefile to geoJSON format in QGIS.
First, let’s load the required packages
library(dplyr) # for manipulating data
library(maptools) # for creating SpatialPointsDataFrames
library(rgdal) # for reading geoJSON ward boundary spatial data
library(leaflet) # for interactive mapping
then download the STATS19 casualty data
casualties <- read.csv("https://www.tfl.gov.uk/cdn/static/cms/documents/2014-gla-data-extract-casualty.csv", header = T)
casualties$X <- NULL
glimpse(casualties)
## Observations: 30785
## Variables:
## $ AREFNO (fctr) 0114CP00001, 0114CP00002, 0114CP00003, ...
## $ Borough (fctr) CITY OF LONDON, CITY OF LONDON, CITY OF...
## $ Boro (int) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ Easting (int) 533540, 532680, 532090, 531770, 533130, ...
## $ Northing (int) 181230, 181430, 181830, 180950, 180920, ...
## $ CREFNO (int) 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1...
## $ Casualty.Class (fctr) 3 Pedestrian, 3 Pedestrian, 3 Pedestria...
## $ Casualty.Sex (fctr) 1 Male, 1 Male, 1 Male, 1 Male, 1 Male,...
## $ Casualty.Age..Banded. (fctr) 25-59, 25-59, Unknown, 25-59, 25-59, 25...
## $ Casualty.Age (int) 29, 48, 0, 33, 31, 41, 53, 26, 0, 35, 40...
## $ No..of.Casualties (int) 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1...
## $ Casualty.Severity (fctr) 3 Slight, 3 Slight, 2 Serious, 2 Seriou...
## $ Ped..Location (fctr) 05 Crossing Road (Not On Xing), 05 Cros...
## $ Ped..Movement (fctr) 9 Unknown Or Other, 9 Unknown Or Other,...
## $ Mode.of.Travel (fctr) 1 Pedestrian, 1 Pedestrian, 1 Pedestria...
relabel the values in the “Casualty.Severity”
casualties$Casualty.Severity <- factor(casualties$Casualty.Severity,
levels= c("1 Fatal", "2 Serious", "3 Slight"),
labels= c("Fatal", "Serious", "Slight"))
and “Mode.of.Travel” variables
casualties$Mode.of.Travel <- factor(casualties$Mode.of.Travel,
levels= c("1 Pedestrian", "2 Pedal Cycle", "3 Powered 2 Wheeler", "4 Car",
"5 Taxi", "6 Bus Or Coach", "7 Goods Vehicle", "8 Other Vehicle"),
labels= c("Pedestrian", "Pedal Cycle", "Powered 2 Wheeler", "Car",
"Taxi", "Bus or Coach", "Goods Vehicle", "Other Vehicle"))
Then, check the results
table(casualties$Mode.of.Travel, casualties$Casualty.Severity)
##
## Fatal Serious Slight
## Pedestrian 64 715 4834
## Pedal Cycle 13 419 4714
## Powered 2 Wheeler 27 499 4707
## Car 19 297 11487
## Taxi 0 13 628
## Bus or Coach 0 71 1508
## Goods Vehicle 2 19 631
## Other Vehicle 2 7 109
Now subset the casualties by “Casualty.Severity” (e.g. Fatal and Serious) and “Mode.of.Travel” (e.g. Pedal Cycle) and retain only the distinct rows
collisions <- casualties %>%
filter(Casualty.Severity == "Fatal" & Mode.of.Travel == "Pedal Cycle" | Casualty.Severity == "Serious" & Mode.of.Travel == "Pedal Cycle") %>%
distinct(AREFNO)
which leave collisions involving fatal or serious injury to a pedal cyclist
table(collisions$Mode.of.Travel, collisions$Casualty.Severity)
##
## Fatal Serious Slight
## Pedestrian 0 0 0
## Pedal Cycle 13 418 0
## Powered 2 Wheeler 0 0 0
## Car 0 0 0
## Taxi 0 0 0
## Bus or Coach 0 0 0
## Goods Vehicle 0 0 0
## Other Vehicle 0 0 0
Then download the STATS19 attendant data to add in the “Accident.Date”
attendant <- read.csv("https://tfl.gov.uk/cdn/static/cms/documents/2014-gla-data-extract-attendant.csv", header=T)
attendant$Accident.Date <- as.Date(attendant$Accident.Date, "%d-%b-%y")
attendant <- attendant %>%
select(AREFNO, Accident.Date)
collisions <- merge(collisions, attendant, by="AREFNO")
rm(attendant)
Then add a variable which is a concatenation of incident details. This will be used as a popup in the final map output.
collisions_desc <- function(row)
with(as.list(row), paste0(format.Date(Accident.Date, "%d-%b-%y"), ":</b> A ",
tolower(Casualty.Severity), " collision involving a ", tolower(Mode.of.Travel)))
strs <- apply(collisions, 1, collisions_desc)
names(strs) <- NULL
collisions$text <- strs
Now, convert the collision data to a SpatialPointsDataFrame
coords <- SpatialPoints(collisions[,c("Easting","Northing")])
collisions.pts <- SpatialPointsDataFrame(coords,collisions)
proj4string(collisions.pts) <- CRS("+init=epsg:27700")
collisions.pts <- spTransform(collisions.pts, CRS("+init=epsg:4326"))
read the ward boundary spatial data
wards = readOGR("/Users/henrypartridge/Dropbox/R/rpubs/mapping_in_leaflet/wards.geojson", "OGRGeoJSON", verbose = FALSE)
proj4string(collisions.pts) <- proj4string(wards)
and count the number of collisions in each ward.
pointsinpolygon <- over(SpatialPolygons(wards@polygons), SpatialPoints(collisions.pts), returnList = TRUE)
wards$count <- unlist(lapply(pointsinpolygon, length))
wards <- wards[wards$count != 0,]
Finally, use the Leaflet package to create an interactive map by setting the classification scheme
pal = colorBin('RdPu', wards$count, bins = 5, pretty = TRUE, na.color = "#808080")
creating a ward popup
wards_popup <- paste0("<strong>Ward: </strong>", wards$NAME,
"<br><strong>Borough: </strong>", wards$BOROUGH,
"<br><strong>Pedal cycle KSIs (2014): </strong>", wards$count)
a pedal cycle icon
icon <- iconList(freq = makeIcon("/Users/henrypartridge/Dropbox/R/rpubs/mapping_in_leaflet/bicycle.png", iconWidth = 12, iconHeight = 12))
and plotting the results.
leaflet(data = wards) %>%
addProviderTiles("CartoDB.Positron") %>%
setView(-0.103894, 51.503971, zoom = 13) %>%
addPolygons(fillOpacity = 0.7,
fillColor = ~pal(count), color = "darkgrey", weight = 2, popup = wards_popup) %>%
addLegend(position = c("bottomright"), pal = pal, values = ~count, opacity = 0.7, title = 'Count of collisions') %>%
addMarkers(data = collisions.pts, icon = icon, popup = ~text)
The map shows the ward-level distribution of collisions involving fatal or serious injury to pedal cyclists during 2014. Please note that the count of pedal cycle KSIs can be obtained by clicking on each ward and the date and severity of each collision by clicking a pedal cycle icon.