knitr::opts_chunk$set(
  echo = TRUE,
  collapse = TRUE,
  comment = "#>"
)

Introduction

This document demonstrates the data outputs from the ACTON project based on case study regions. It is a reproducible technical document with code that shows how to get the results with the acton package. To reproduce the results you must first install the acton package as follows:

remotes::install_github("cyipt/acton")
library(acton)
library(dplyr)
library(tmap)
tmap_mode("view")

A case study of Leeds

Data from PlanIt, accessed using the acton R package, was used to identify four recent large planning applications:

The following code gets and subsets the relevant PlanIt data for Leeds:

# note work in progress!
applications_leeds = get_planit_data(
  limit = 500,
  auth = "Leeds",
  app_size = "large",
  app_state = "permitted"
  )
nrow(applications_leeds)
tm_shape(applications_leeds) + tm_dots(col = "app_type") +
  tm_basemap(server = "CartoDB.Positron")

The result in the applications_leeds object contains much rich information about the planning applications, under the following column headings:

names(applications_leeds)
DT::datatable(applications_leeds[-c(1, 9, 11, 12, 13, 18, 21)])

The following code gets the specific applications we will use for this case study of Leeds:

ids = c(
  "13/05235/FU",
  "15/04151/FU",
  "15/00415/FU",
  "15/01973/FU"
)
applications_case_study = applications_leeds[
  applications_leeds$uid %in% ids,
]
nrow(applications_case_study)
# aim: save case study applications
applications_case_study_leeds = applications_case_study
usethis::use_data(applications_case_study_leeds)

The descripton of each is shown in the table below, with context shown for each in the following subsections:

applications_case_study %>% 
  sf::st_drop_geometry() %>% 
  select(description, url) %>% 
  knitr::kable()
# # Aim: in future subset from the results when the API gives all large applications
# application_ids = c(
#   "13/05235/FU@Leeds",
#   "15/04151/FU@Leeds",
#   "15/00415/FU@Leeds",
#   "15/01973/FU@Leeds"
# )
# # get_planit_data(query_type = "planapplic", query_value = application_ids)
# applications_case_study_list = lapply(
#   application_ids,
#   get_planit_data,
#   query_type = "planapplic"
#   )
# application_variable_names = sapply(applications_case_study_list, names)
# applications_consistent_names = lapply(applications_case_study_list, function(x) {
#   x[application_variable_names[[1]]]
# })
# applications_case_study = do.call(what = rbind, applications_consistent_names)

We will describe the Allerton Bywater application in more depth and use it to illustrate the data returned by the PlanIt API, before describing the other development sites.

Allerton Bywater Millennium Community

Data on the application

The planning application we have selected for Allerton Bywater relates to the final phase of the Millennium Community. This includes 189 homes and has planning consent 13/05235/FU.

We can see that this is classified by PlanIt.org.uk as a large application. The application was submitted in December 2013 by Keepmoat Homes and the Homes and Communities Agency and was approved in November 2014.

Available fields include links to the full PlanIt record and to planning application information from Leeds City Council.

allerton_bywater = applications_case_study[applications_case_study$uid == "13/05235/FU",]
allerton_bywater$description
allerton_bywater$link
allerton_bywater$url
allerton_bywater$app_state
allerton_bywater$app_size
allerton_bywater$app_type
allerton_bywater$address
allerton_bywater$start_date
allerton_bywater$decided_date

The original outline planning application for the entire Allerton Bywater Millennium Community can be found as follows. This was submitted in November 2000 and approved in August 2002.

allerton_bywater_original = get_planit_data(query_type = "planapplic", query_value = "33/311/00/OT@Leeds")
allerton_bywater_original$description
allerton_bywater_original$url
allerton_bywater_original$start_date
allerton_bywater_original$decided_date

Other Leeds case study sites

An overview of the four case study sites is shown in the map below.

applications_case_study$site = as.factor(c("Tyersal","Micklefield","Leeds Climate Innovation District","Allerton Bywater"))
tm_shape(applications_case_study) +
  tm_dots(col = "site", size = 0.1)  +
  tm_basemap(server = "CartoDB.Positron")

Leeds Climate Innovation District

Micklefield

Tyersal

Accessibility indicators

Journey time statistics (JTS) are available from the Department for Transport recording accessibility at the geographical level of the LSOA (an area covering approximately 1500 residents or 650 households). The statistics include average minimum travel times to key local services and destinations, such as town centres, centres of employment, primary schools, secondary schools, food stores and GP surgeries.

Travel times are calculated for three modes of travel - by car, by cycle, and by a mode that combines walking and public transport.

In the following code we download data for journey times to the nearest centres of employment, town centres, food stores, primary schools, secondary schools and GP surgeries.

There are several different statistics representing employment centres. We combine measures for employment centres of different sizes to create a single employment metric. We then combine this with the other journey time statistics to generate a single index of accessibility for each mode of travel.

library(dplyr)

zones_leeds = pct::get_pct_zones(region = "west-yorkshire", geography = "lsoa", purpose = "commute") %>% rename(LA_Code = lad11cd) %>% st_set_crs(4326)

which(st_is_valid(zones_leeds) == FALSE)
zones_leeds = lwgeom::st_make_valid(zones_leeds)
which(st_is_valid(zones_leeds) == FALSE)

access_employ = get_jts_data("jts0501", 2017)
access_town = get_jts_data("jts0508", 2017)
access_food = get_jts_data("jts0507", 2017)
access_primary = get_jts_data("jts0502", 2017)
access_secondary = get_jts_data("jts0503", 2017)
access_gp = get_jts_data("jts0505", 2017)

access_employ$weightedJobsPTt = apply(
  X = access_employ[c("Jobs100EmpPTt", "Jobs500EmpPTt", "Jobs5000EmpPTt")],
  MARGIN = 1,
  FUN = weighted.mean,
  w = c(100, 500, 5000)
)
access_employ$weightedJobsCyct = apply(
  X = access_employ[c("Jobs100EmpCyct", "Jobs500EmpCyct", "Jobs5000EmpCyct")],
  MARGIN = 1,
  FUN = weighted.mean,
  w = c(100, 500, 5000)
)
access_employ$weightedJobsCart = apply(
  X = access_employ[c("Jobs100EmpCart", "Jobs500EmpCart", "Jobs5000EmpCart")],
  MARGIN = 1,
  FUN = weighted.mean,
  w = c(100, 500, 5000)
)

zones_leeds = inner_join(zones_leeds,access_town,by = c("geo_code" = "LSOA_code","LA_Code"))
zones_leeds = inner_join(zones_leeds,access_food,by = c("geo_code" = "LSOA_code","LA_Code"))
zones_leeds = inner_join(zones_leeds,access_employ,by = c("geo_code" = "LSOA_code","LA_Code"))
zones_leeds = inner_join(zones_leeds,access_primary,by = c("geo_code" = "LSOA_code","LA_Code"))
zones_leeds = inner_join(zones_leeds,access_secondary,by = c("geo_code" = "LSOA_code","LA_Code"))
zones_leeds = inner_join(zones_leeds,access_gp,by = c("geo_code" = "LSOA_code","LA_Code"))

zones_leeds = zones_leeds %>%
  mutate(
    index_PT = (weightedJobsPTt+TownPTt+FoodPTt+PSPTt+SSPTt+GPPTt)/6,
    index_Cyc = (weightedJobsCyct+TownCyct+FoodCyct+PSCyct+SSCyct+GPCyct)/6,
    index_Car = (weightedJobsCart+TownCart+FoodCart+PSCart+SSCart+GPCart)/6
    )
# sf::write_sf(zones_leeds, "zones_leeds_lsoa.geojson")
# piggyback::pb_upload("zones_leeds_lsoa.geojson")
# piggyback::pb_download_url("zones_leeds_lsoa.geojson")
zones_leeds = sf::read_sf("https://github.com/cyipt/acton/releases/download/0.0.1/zones_leeds_lsoa.geojson")

Now we can map the journey time statistics across Leeds and West Yorkshire.

The first map shows the LSOA zones in West Yorkshire together with their working age population. LSOA population should normally be relatively constant, but it is considerably higher in some Leeds LSOAs. This may be due to new residential developments built after the LSOA boundaries were set, in particular student accommodation and the recent growth in city centre living.

qtm(zones_leeds, "Empl_pop")

Multiple statistics are available for access to centres of employment, including travel time to locations with 100-499 jobs, to locations with 500-4999 jobs, and to locations with 5000+ jobs. As explained earlier, we have combined these three statistics to produce a single measure weighted by the number of jobs. This is shown in the maps below.

tm_shape(zones_leeds) +
  tm_polygons(c("weightedJobsPTt","weightedJobsCyct","weightedJobsCart"),palette="-cividis",title = c("Walk/PT","Cycle","Car") +
  tm_shape(applications_case_study) +
  tm_dots(size=0.2) +
  tm_facets(nrow = 1)
knitr::include_graphics("https://user-images.githubusercontent.com/52210872/76424159-c7b99680-639f-11ea-95c5-1198d977be1f.png")

We have then combined the weighted access to employment measure with the measures for access to food stores, town centres, primary schools, secondary schools and GPs. By adding together all of these scores we have generated a single accessibility index for each mode of travel.

tm_shape(zones_leeds) +
  tm_polygons(c("index_PT","index_Cyc","index_Car"),palette="-viridis",title = c("Walk/PT","Cycle","Car") +
  tm_shape(applications_case_study) +
  tm_dots(size=0.2) +
  tm_facets(nrow = 1)
knitr::include_graphics("https://user-images.githubusercontent.com/52210872/76458014-bdb08b80-63d1-11ea-88dd-a5da8020ea5d.png")

According to these measures, there are many areas that have poor accessibility by active modes and public transport.

Route busyness

These maps use OD data for journeys to work from the LSOA centroid closest to each site, but changing to point of origin of the journeys so they start at our case study sites. The desire lines are converted to routes using 'fastest journey' option of the cyclestreets::journey() function.

The thickness of the lines is proportional to the number of journeys (using all modes of transport), and the colour represents the busyness of the roads.

We can see there are some roads used by commuters from these sites that are particularly busy. These include the A63 near Garforth and the A61 on the eastern edge of Leeds City Centre (circle these roads). However, an integral component of the Leeds Climate Innovation District is the construction of a new foot and cycle bridge over the River Aire. This bridge is already in place and allows residents to access Leeds city centre via an off-road riverside path, avoiding the need to use the A61. We should model how this bridge impacts the accessiblity of the site.

knitr::include_graphics("https://user-images.githubusercontent.com/52210872/73958076-43d34100-48ff-11ea-80a3-f06f8205e8d2.png")
knitr::include_graphics("https://user-images.githubusercontent.com/52210872/73958097-4b92e580-48ff-11ea-9475-5332580f7083.png")
knitr::include_graphics("https://user-images.githubusercontent.com/52210872/75466061-79f56500-5981-11ea-85af-d154cb907be8.png")
knitr::include_graphics("https://user-images.githubusercontent.com/52210872/73958128-58173e00-48ff-11ea-8cdb-00eb2ca66060.png")

Joining on active transport variables

# zone_centroids = pct::get_pct_centroids()
applications_joined = sf::st_join(applications_case_study,
            zones_leeds %>% select(index_PT, index_Cyc, index_Car)
            ) 
# applications_joined = sf::st_join(applications_case_study,
#             zones_leeds %>% select(index_PT, index_Cyc, index_Car)
#             , join = st_nearest_feature 
#             ) 
plot(applications_joined %>% select(matches("index")))

Indicators

The next stage is to convert the rich data we now have for each development into an indicator of active transport provision. That is covered in the next article.



cyipt/acton documentation built on Jan. 29, 2021, 7:30 a.m.