Propensity to Cycle Tool Advanced Workshop

Introduction

This vignette supports workshops on advanced usage and development of the Propensity to Cycle Tool (PCT). Beginner and intermediate PCT events focus on using the PCT via the web application hosted at www.pct.bike and the data provided by the PCT in QGIS.

The focus here is on analysing cycling potential in the open source statistical programming language R, in which the majority of the PCT was built. It will show how the code underlying the PCT works, how the underlying data can be accessed for reproducible analysis, and how the methods can be used to generate new scenarios of cycling uptake.

If you are an intermediate user, it may be worth brushing-up on your R skills, e.g. by taking a free online course such as that provided by DataCamp or by working through Chapter 2 onwards of the open source book Geocomputation with R (see reading list below for more transport-specific resources).

Prior reading

In addition to computer hardware (a laptop) and software (an up-to-date R set-up and experience using R) pre-requisites, you should have read, or at least have working knowledge of the contents of, the following publications, all of which are freely available online:

Prerequisites

To ensure your computer is ready for the course, you should be able to run the following lines of R code on your computer:

install.packages("remotes")
pkgs = c(
  "cyclestreets",
  "mapview",
  "pct",
  "sf",
  "stats19",
  "stplanr",
  "tidyverse",
  "devtools"
)
remotes::install_cran(pkgs)
# remotes::install_github("ITSLeeds/pct")

To test your computer is ready to work with PCT data in R, try running the following command:

source("https://github.com/ITSLeeds/pct/raw/master/inst/test-setup.R") 

Agenda

Part 1: how the Propensity to Cycle Tool works + demo: ‘I do’

Part 2: Co-coding session: getting started with transport data in R: ‘we do’

Part 3: using PCT data for local transport planning: ‘you do’

Exercises

How the PCT works and what you can use it for

The PCT provides data at 4 geographic levels:

Which types of data are most appropriate to tackle each of the questions/problems you identified?

Getting PCT data

In this section we will get PCT data at the MSOA level and plot the result in a simple map.

library(pct)
library(dplyr)   # in the tidyverse
library(tmap)    # installed alongside mapview
region_name = "isle-of-wight"
zones_all = get_pct_zones(region_name, geography = "msoa")
lines_all = get_pct_lines(region_name, geography = "msoa")
routes_all = get_pct_routes_fast(region_name, geography = "msoa")
rnet_all = get_pct_rnet(region_name)
plot(zones_all$geometry)
plot(lines_all$geometry, col = "blue", add = TRUE)
plot(routes_all$geometry, col = "green", add = TRUE)
plot(rnet_all$geometry, col = "red", lwd = rnet_all$bicycle / 10, add = TRUE)

Visualising PCT data

At its heart, the PCT is a data visualisation tool.

tm_shape(rnet_all) +
  tm_lines(lwd = "dutch_slc", scale = 9)
#> Legend labels were too wide. Therefore, legend.text.size has been set to 0.47. Increase legend.width (argument of tm_layout) to make the legend wider and therefore the labels larger.

# interactive plot
tmap_mode("view")
#> tmap mode set to interactive viewing
tm_shape(rnet_all) +
  tm_lines(lwd = "dutch_slc", scale = 9)
#> Legend for line widths not available in view mode.
# basic plot
max_distance = 7
# plot(zones_all$geometry)
# plot(lines_all$geometry[lines_all$all > 500], col = "red", add = TRUE)

# create 'active' desire lines (less than 5 km)
active = lines_all %>% 
  mutate(`Percent Active` = (bicycle + foot) / all * 100) %>% 
  filter(e_dist_km < max_distance)

tm_shape(active) +
  tm_lines("Percent Active", palette = "RdYlBu", lwd = "all", scale = 9)
# Create car dependent desire lines
car_dependent = lines_all %>% 
  mutate(`Percent Drive` = (car_driver) / all * 100) %>% 
  filter(e_dist_km < max_distance)
tm_shape(car_dependent) +
  tm_lines("Percent Drive", palette = "-RdYlBu", lwd = "all", scale = 9)
#> Legend for line widths not available in view mode.

Advanced: visualise the PCT data using a range of visualisation techniques. For inspiration, check out the Making maps with R chapter of Geocomputation with R.

Exploring PCT data

z = zones_all %>% 
  select(geo_code, geo_name, all, foot, bicycle, car_driver)

# Aim: get top 5 cycle routes
l_msoa = lines_all %>% 
  select(geo_code1, geo_code2, all, foot, bicycle, car_driver, rf_avslope_perc, rf_dist_km)
Top 5 MSOA to MSOA desire lines with highest number of people cycling (left) and driving (right) in the Isle of Wight.Top 5 MSOA to MSOA desire lines with highest number of people cycling (left) and driving (right) in the Isle of Wight.

Top 5 MSOA to MSOA desire lines with highest number of people cycling (left) and driving (right) in the Isle of Wight.

Top 10 LSOA-LSOA desire lines with highest number of people cycling (left) and driving (right) in the Isle of Wight.Top 10 LSOA-LSOA desire lines with highest number of people cycling (left) and driving (right) in the Isle of Wight.

Top 10 LSOA-LSOA desire lines with highest number of people cycling (left) and driving (right) in the Isle of Wight.

Modifying PCT data to identify routes/roads of interest

l_msoa$pcycle = l_msoa$bicycle / l_msoa$all * 100
# plot(l_msoa["pcycle"], lwd = l_msoa$all / mean(l_msoa$all), breaks = c(0, 5, 10, 20, 50))
#> [1] 0.5726026
plot(l_less_than_10km %>% filter(foot > 5) %>% select(foot))
plot(l_less_than_10km %>% filter(bicycle > 5) %>% select(bicycle))
plot(l_less_than_10km %>% filter(car_driver > 5) %>% select(car_driver))

Scenarios of change

l_msoa$euclidean_distance = as.numeric(sf::st_length(l_msoa))
l_msoa$pcycle_govtarget = uptake_pct_govtarget_2020(
  distance = l_msoa$rf_dist_km,
  gradient = l_msoa$rf_avslope_perc
  ) * 100 + l_msoa$pcycle
Percent cycling currently (left) and under a 'Go Dutch' scenario (right) in the Isle of Wight.Percent cycling currently (left) and under a 'Go Dutch' scenario (right) in the Isle of Wight.

Percent cycling currently (left) and under a ‘Go Dutch’ scenario (right) in the Isle of Wight.

Routing

l_top = l_msoa %>% 
  top_n(n = 1, wt = bicycle)

Route networks

route_data = sf::st_sf(wight_lines_30, geometry = wight_routes_30$geometry)

Ideas for further work and a ‘minihack’

References

Goodman, Anna, Ilan Fridman Rojas, James Woodcock, Rachel Aldred, Nikolai Berkoff, Malcolm Morgan, Ali Abbas, and Robin Lovelace. 2019. “Scenarios of Cycling to School in England, and Associated Health and Carbon Impacts: Application of the Propensity to Cycle Tool.” Journal of Transport & Health 12 (March): 263–78. https://doi.org/10.1016/j.jth.2019.01.008.
Lovelace, Robin, Anna Goodman, Rachel Aldred, Nikolai Berkoff, Ali Abbas, and James Woodcock. 2017. “The Propensity to Cycle Tool: An Open Source Online System for Sustainable Transport Planning.” Journal of Transport and Land Use 10 (1). https://doi.org/10.5198/jtlu.2016.862.
Lovelace, Robin, Jakub Nowosad, and Jannes Meunchow. 2019. Geocomputation with R. CRC Press. https://geocompr.robinlovelace.net/.