104 | - Information on how to create reproducible examples (this will be
105 | useful when asking for help during the workshop):
106 |
107 |
108 | Hope this is useful, please prioritise getting R up-and-running and let
109 | us know if you have any issues.
110 |
111 | All the best,
112 |
113 | Robin
114 |
115 | P.s. there is one more thing to say: we plan a virtual ‘to the pub’
116 | session after the event from 5pm to 6pm so make sure you have beer (or
117 | whatever refreshment takes your fancy) in stock if you want to join for
118 | a post workshop social.
119 |
--------------------------------------------------------------------------------
/data-raw/workshop-msg_files/figure-gfm/unnamed-chunk-2-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/data-raw/workshop-msg_files/figure-gfm/unnamed-chunk-2-1.png
--------------------------------------------------------------------------------
/data-raw/workshop-msg_files/figure-gfm/unnamed-chunk-3-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/data-raw/workshop-msg_files/figure-gfm/unnamed-chunk-3-1.png
--------------------------------------------------------------------------------
/data-raw/workshop-msg_files/figure-gfm/unnamed-chunk-3-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/data-raw/workshop-msg_files/figure-gfm/unnamed-chunk-3-2.png
--------------------------------------------------------------------------------
/data-raw/workshop-msg_files/figure-gfm/unnamed-chunk-3-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/data-raw/workshop-msg_files/figure-gfm/unnamed-chunk-3-3.png
--------------------------------------------------------------------------------
/data-raw/workshop-msg_files/figure-gfm/unnamed-chunk-3-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/data-raw/workshop-msg_files/figure-gfm/unnamed-chunk-3-4.png
--------------------------------------------------------------------------------
/data-raw/workshop-msg_files/figure-gfm/unnamed-chunk-4-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/data-raw/workshop-msg_files/figure-gfm/unnamed-chunk-4-1.png
--------------------------------------------------------------------------------
/data-raw/workshop-msg_files/figure-html/unnamed-chunk-2-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/data-raw/workshop-msg_files/figure-html/unnamed-chunk-2-1.png
--------------------------------------------------------------------------------
/data/desire_lines_leeds.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/data/desire_lines_leeds.rda
--------------------------------------------------------------------------------
/data/leeds_uber_sample.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/data/leeds_uber_sample.rda
--------------------------------------------------------------------------------
/data/mode_names.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/data/mode_names.rda
--------------------------------------------------------------------------------
/data/od_leeds.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/data/od_leeds.rda
--------------------------------------------------------------------------------
/data/pct_regions.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/data/pct_regions.rda
--------------------------------------------------------------------------------
/data/pct_regions_lookup.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/data/pct_regions_lookup.rda
--------------------------------------------------------------------------------
/data/rnet_leeds.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/data/rnet_leeds.rda
--------------------------------------------------------------------------------
/data/routes_fast_leeds.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/data/routes_fast_leeds.rda
--------------------------------------------------------------------------------
/data/santiago_lines.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/data/santiago_lines.rda
--------------------------------------------------------------------------------
/data/santiago_od.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/data/santiago_od.rda
--------------------------------------------------------------------------------
/data/santiago_routes_cs.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/data/santiago_routes_cs.rda
--------------------------------------------------------------------------------
/data/santiago_zones.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/data/santiago_zones.rda
--------------------------------------------------------------------------------
/data/wight_centroids.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/data/wight_centroids.rda
--------------------------------------------------------------------------------
/data/wight_lines_30.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/data/wight_lines_30.rda
--------------------------------------------------------------------------------
/data/wight_lines_pct.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/data/wight_lines_pct.rda
--------------------------------------------------------------------------------
/data/wight_od.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/data/wight_od.rda
--------------------------------------------------------------------------------
/data/wight_rnet.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/data/wight_rnet.rda
--------------------------------------------------------------------------------
/data/wight_routes_30.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/data/wight_routes_30.rda
--------------------------------------------------------------------------------
/data/wight_routes_30_cs.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/data/wight_routes_30_cs.rda
--------------------------------------------------------------------------------
/data/wight_zones.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/data/wight_zones.rda
--------------------------------------------------------------------------------
/data/zones_leeds.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/data/zones_leeds.rda
--------------------------------------------------------------------------------
/inst/cycling-potential-to-specific-zones.R:
--------------------------------------------------------------------------------
1 | # Cycling potential to leeds valley park
2 |
3 | library(tidyverse)
4 | library(osmdata)
5 | library(stplanr)
6 | library(pct)
7 |
8 |
9 | # with osmdata
10 | lvp_osm = opq("leeds") %>%
11 | add_osm_feature("name", "")
12 | lvp_sf = osmdata_sf(lvp_osm)
13 |
14 | # with geofabric
15 | devtools::install_github("itsleeds/geofabric")
16 | library(geofabric)
17 | # View(geofabric_zones)
18 | # wy_osm = get_geofabric("west yorkshire")
19 | # wy_osm = get_geofabric("west yorkshire", layer = "multipolygons")
20 | f = geofabric::gf_filename(name = "West Yorkshire")
21 | query = "select * from multipolygons where name = 'Leeds Valley Park'"
22 | lvp = sf::read_sf(f, query = query)
23 | plot(lvp[1, ])
24 | lvp = lvp[1, ]
25 | sf::write_sf(lvp, "lvp.geojson")
26 | piggyback::pb_upload("lvp.geojson")
27 |
28 | # get od data
29 | od = pct::get_od()
30 | od
31 |
32 | # get centroids data
33 | centroids = pct::get_pct_centroids(region = "west-yorkshire")
34 |
35 | msoa_codes_study_area = c("E02006876", "E02002423")
36 |
37 | summary(od$geo_code2 %in% msoa_codes_study_area)
38 | od_wy = od %>%
39 | filter(geo_code1 %in% centroids$geo_code)
40 |
41 | od_wy_lvp = od_wy %>%
42 | filter(geo_code2 %in% msoa_codes_study_area)
43 |
44 | class(od_wy_lvp)
45 | class(centroids)
46 | mapview::mapview(centroids)
47 |
48 | desire_lines_lvp = od2line(flow = od_wy_lvp, centroids)
49 | mapview::mapview(desire_lines_lvp)
50 |
51 | sum(desire_lines_lvp$all)
52 | mean(centroids$all)
53 |
54 |
55 | desire_lines_lvp$hilliness = 0.01
56 | desire_lines_lvp$distance = as.numeric(sf::st_length(desire_lines_lvp))
57 |
58 | desire_lines_lvp$potential_cycling = pct::uptake_pct_godutch(
59 | distance = desire_lines_lvp$distance,
60 | gradient = desire_lines_lvp$hilliness
61 | )
62 |
63 | plot(desire_lines_lvp$distance, desire_lines_lvp$potential_cycling)
64 |
65 | hist(desire_lines_lvp$all, breaks = 10)
66 |
67 | # get route data from pct
68 |
69 | pct_routes = get_pct_routes_fast(region = "west-yorkshire")
70 |
71 | pct_routes_lvp = pct_routes %>%
72 | filter(geo_code1 %in% msoa_codes_study_area | geo_code2 %in% msoa_codes_study_area)
73 |
74 | ids_lvp = od_id_order(x = desire_lines_lvp)
75 | desire_lines_lvp$id = ids_lvp$stplanr.key
76 |
77 | ids_routes = od_id_order(x = pct_routes_lvp[2:3])
78 | pct_routes_lvp$id = ids_routes$stplanr.key
79 |
80 | # check matches
81 | summary(desire_lines_lvp$id %in% pct_routes_lvp$id)
82 |
83 | names(desire_lines_lvp)
84 | pct_routes_small = pct_routes_lvp %>%
85 | select(all_bidirection = all, bicycle_bidirectional = bicycle, rf_dist_km, rf_avslope_perc, id) %>%
86 | filter(id %in% desire_lines_lvp$id)
87 | names(pct_routes_small)
88 |
89 | desire_lines_non_spatial = sf::st_drop_geometry(desire_lines_lvp) %>%
90 | filter(id %in% pct_routes_small$id)
91 | routes_lvp = right_join(pct_routes_small, desire_lines_non_spatial)
92 |
93 | mapview::mapview(routes_lvp)
94 |
95 | # recalculate cycling potential based on better data
96 | summary(routes_lvp$all)
97 | summary(pct_routes$all)
98 | plot(routes_lvp$geometry, lwd = routes_lvp$bicycle)
99 |
100 | rnet_lvp = overline2(routes_lvp, attrib = "bicycle")
101 |
102 | library(tmap)
103 | tmap_mode("view")
104 | tm_shape(rnet_lvp) +
105 | tm_lines(lwd = "bicycle", scale = 9)
106 |
107 |
108 | # calculate go dutch ------------------------------------------------------
109 |
110 | plot(routes_lvp$bicycle, routes_lvp$bicycle_bidirectional)
111 | plot(routes_lvp$distance, routes_lvp$rf_dist_km)
112 | routes_lvp$go_dutch_percent = pct::uptake_pct_godutch(
113 | distance = routes_lvp$rf_dist_km,
114 | gradient = routes_lvp$rf_avslope_perc
115 | )
116 |
117 | plot(routes_lvp$distance, routes_lvp$go_dutch_percent)
118 | routes_lvp$go_dutch = routes_lvp$go_dutch_percent * routes_lvp$all
119 | summary(routes_lvp$go_dutch)
120 | sum(routes_lvp$go_dutch)
121 |
122 | rnet_lvp_go_dutch = overline2(routes_lvp, attrib = "go_dutch")
123 | tm_shape(rnet_lvp_go_dutch) +
124 | # tm_basemap(server = leaflet::providers$Thunderforest.OpenCycleMap) +
125 | tm_lines(lwd = "go_dutch", scale = 9)
126 |
127 |
128 | # get postcode locations --------------------------------------------------
129 |
130 | remotes::install_github("ropensci/PostcodesioR")
131 | library(PostcodesioR)
132 |
133 | # simple reproducible example
134 | od_postcode = readRDS(url("https://github.com/ITSLeeds/pct/releases/download/0.2.5/od_postcode_min.Rds"))
135 | post_code_points = readRDS(url("https://github.com/ITSLeeds/pct/releases/download/0.2.5/post_code_points_min.Rds"))
136 | lvp_centroid = sf::read_sf("https://github.com/ITSLeeds/pct/releases/download/0.2.5/lvp.geojson")
137 | desire_lines_lvp = stplanr::od2line(flow = od_postcode, post_code_points, lvp_centroid)
138 |
139 | # on many postcodes -------------------------------------------------------
140 |
141 |
142 |
143 |
144 | # pcodes = readxl::read_excel("Copy of LVP 2019 Travel Survey_Postcodes only.xlsx")
145 | names(pcodes)[1] = "code"
146 | stplanr::geo_code(pcodes[[1]][181]) # test - fail
147 | stplanr::geo_code("ls10 3xe")
148 | tmaptools::geocode_OSM("ls10 3xe")
149 | PostcodesioR::postcode_lookup("ls10 3xe")
150 | PostcodesioR::bulk_postcode_lookup(postcodes = list(pcodes$code[100:109]))
151 |
152 | pc_list <- list(
153 | postcodes = c("PR3 0SG", "M45 6GN", "EX165BL")) # spaces are ignored
154 | bulk_postcode_lookup(pc_list)
155 |
156 | summary(nchar(pcodes$code))
157 | pcodes_complete = pcodes %>%
158 | filter(str_detect(code, " ")) %>%
159 | filter(nchar(code) > 6) %>%
160 | filter(nchar(code) < 9) %>%
161 | mutate(code = gsub(pattern = " ", replacement = "", x = code))
162 |
163 | pcodes_list = list(postcodes = pcodes_complete$code[100:109])
164 |
165 |
166 | pcodes_list = list(postcodes = pcodes$code[100:109])
167 | bulk_postcode_lookup(postcodes = pcodes_list) # works!
168 |
169 | pcodes_list = list(postcodes = pcodes$code[1:100])
170 | pcode_result_1_100 = bulk_postcode_lookup(postcodes = pcodes_list) # works!
171 |
172 | library(purrr)
173 |
174 | bulk_list <- lapply(pcode_result_1_100, "[[", 2)
175 |
176 | bulk_df <-
177 | map_dfr(bulk_list,
178 | `[`,
179 | c("postcode", "longitude", "latitude"))
180 |
181 | post_code_points = sf::st_as_sf(bulk_df, coords = c("longitude", "latitude"), crs = 4326)
182 | mapview::mapview(post_code_points)
183 |
184 | pcodes_list = list(postcodes = pcodes$code[101:200])
185 | pcode_result_100 = bulk_postcode_lookup(postcodes = pcodes_list) # works!
186 | pcodes_list = list(postcodes = pcodes$code[201:300])
187 | pcode_result_200 = bulk_postcode_lookup(postcodes = pcodes_list) # works!
188 | pcodes_list = list(postcodes = pcodes$code[301:400])
189 | pcode_result_300 = bulk_postcode_lookup(postcodes = pcodes_list) # works!
190 | pcodes_list = list(postcodes = pcodes$code[401:500])
191 | pcode_result_400 = bulk_postcode_lookup(postcodes = pcodes_list) # works!
192 | pcodes_list = list(postcodes = pcodes$code[501:600])
193 | pcode_result_500 = bulk_postcode_lookup(postcodes = pcodes_list) # works!
194 | pcodes_list = list(postcodes = pcodes$code[601:700])
195 | pcode_result_600 = bulk_postcode_lookup(postcodes = pcodes_list) # works!
196 | pcodes_list = list(postcodes = pcodes$code[701:nrow(pcodes)])
197 | pcode_result_700 = bulk_postcode_lookup(postcodes = pcodes_list) # works!
198 |
199 | pcodes_list_all = c(
200 | pcode_result_1_100,
201 | pcode_result_100,
202 | pcode_result_200,
203 | pcode_result_300,
204 | pcode_result_400,
205 | pcode_result_500,
206 | pcode_result_600,
207 | pcode_result_700
208 | )
209 |
210 | bulk_list <- lapply(pcodes_list_all, "[[", 2)
211 |
212 | bulk_df <-
213 | map_dfr(bulk_list,
214 | `[`,
215 | c("postcode", "longitude", "latitude"))
216 |
217 | head(bulk_df)
218 | post_code_points = sf::st_as_sf(bulk_df, coords = c("longitude", "latitude"), crs = 4326)
219 | mapview::mapview(post_code_points)
220 | saveRDS(post_code_points, "post_code_points.Rds")
221 |
222 | lvp_centroid = sf::st_centroid(lvp)
223 | od_postcode = sf::st_drop_geometry(post_code_points)
224 | od_postcode$dest = lvp$osm_id
225 | od_postcode$all = 1
226 | summary(od_postcode$postcode %in% post_code_points$postcode)
227 | summary(od_postcode$dest %in% lvp_centroid$osm_id)
228 |
229 | # this fails: issue with stplanr?
230 | desire_lines_lvp = stplanr::od2line(flow = od_postcode, post_code_points, lvp_centroid)
231 |
232 |
233 |
234 | # out-takes ---------------------------------------------------------------
235 |
236 |
237 | # pcodes = tibble::tibble(code = c("LS7 3HB", "LS2 9JT"))
238 | # pcodes_list = list(postcodes = pcodes$code)
239 | # bulk_postcode_lookup(postcodes = pcodes_list) # works!
240 | # bulk_list <- lapply(pcode_result_1_100, "[[", 2)
241 | #
242 | # bulk_df <-
243 | # map_dfr(bulk_list,
244 | # `[`,
245 | # c("postcode", "longitude", "latitude"))
246 | #
247 | # post_code_points = sf::st_as_sf(bulk_df, coords = c("longitude", "latitude"), crs = 4326)
248 | # saveRDS(post_code_points, "post_code_points_min.Rds")
249 | # lvp_centroid = sf::st_centroid(lvp)
250 | # od_postcode = sf::st_drop_geometry(post_code_points)
251 | # od_postcode$dest = lvp$osm_id
252 | # od_postcode$all = 1
253 | # summary(od_postcode$postcode %in% post_code_points$postcode)
254 | # summary(od_postcode$dest %in% lvp_centroid$osm_id)
255 | #
256 | # mapview::mapview(post_code_points) + mapview::mapview(lvp_centroid)
257 | # # this fails: issue with stplanr?
258 | # desire_lines_lvp = stplanr::od2line(flow = od_postcode, post_code_points, lvp_centroid)
259 | #
260 | # # create-reproducible example
261 | # saveRDS(od_postcode, "od_postcode_min.Rds")
262 | # saveRDS(post_code_points, "post_code_points_min.Rds")
263 | # piggyback::pb_upload("od_postcode_min.Rds")
264 | # piggyback::pb_upload("post_code_points_min.Rds")
265 | # piggyback::pb_download_url()
266 | #
267 | # lvp_centroid
268 |
269 |
--------------------------------------------------------------------------------
/inst/estimate-cycling-potential-rnet-leeds-simple-example.R:
--------------------------------------------------------------------------------
1 | library(pct)
2 | library(stplanr)
3 | library(dplyr)
4 |
5 | key = Sys.getenv("CYCLESTREETS")
6 | nchar(key)
7 | desire_lines = desire_lines_leeds # pre-saved data in pct package
8 | desire_lines
9 |
10 | plot(desire_lines_leeds[c("all", "bicycle")])
11 |
12 | routes_fast = route(l = desire_lines_leeds, route_fun = cyclestreets::journey)
13 |
14 | plot(routes_fast) # shows segment level data
15 | nrow(routes_fast)
16 | length(unique(routes_fast$name)) # many overlapping segments
17 | length(unique(routes_fast$distances)) # many overlapping segments, some duplication
18 | length(unique(routes_fast$elevations)) # many overlapping segments, some duplication
19 |
20 | routes_fast_grouped = routes_fast %>%
21 | group_by(area_of_residence, area_of_workplace) %>%
22 | summarise(
23 | distance = sum(distances),
24 | hilliness = sum(abs(diff(elevations))) / distance,
25 | all = unique(all),
26 | bicycle = unique(bicycle)
27 | )
28 |
29 | plot(routes_fast_grouped$distance, routes_fast_grouped$hilliness)
30 | plot(routes_fast_grouped[c("all", "bicycle")])
31 | routes_fast_grouped$dutch_pct_proportion = uptake_pct_godutch(
32 | distance = routes_fast_grouped$distance,
33 | gradient = routes_fast_grouped$hilliness
34 | )
35 | routes_fast_grouped$dutch_pct_proportion
36 | routes_fast_grouped$bicycle_go_dutch = routes_fast_grouped$dutch_pct_proportion *
37 | routes_fast_grouped$all + routes_fast_grouped$bicycle
38 |
39 | routes_fast_grouped_linestring = sf::st_cast(routes_fast_grouped, "LINESTRING")
40 | rnet_go_dutch = overline(routes_fast_grouped_linestring, attrib = "bicycle_go_dutch")
41 | plot(rnet_go_dutch, breaks = c(0, 500, 1000, 4000))
42 |
43 | # an alternative way to calculate the route network - not recommended:
44 | routes_fast_joined = left_join(routes_fast, sf::st_drop_geometry(routes_fast_grouped))
45 | routes_fast_aggregated = routes_fast_joined %>%
46 | group_by(name, distances, elevations) %>%
47 | summarise(bicycle_go_dutch2 = sum(bicycle_go_dutch))
48 | plot(routes_fast_aggregated["bicycle_go_dutch2"], breaks = c(0, 500, 1000, 4000))
49 |
--------------------------------------------------------------------------------
/inst/part-3-getting-pct-data.R:
--------------------------------------------------------------------------------
1 |
2 | # Intro script for Part 3 - Getting and visualising PCT data -----------------
3 |
4 | # find names of pct regions
5 | View(pct_regions_lookup)
6 | pct_regions_lookup$region_name[pct_regions_lookup$lad16nm == "Leeds"]
7 |
8 | # get pct data (travel to work; LSOA level)
9 | region_name = "isle-of-wight"
10 |
11 | iow_zones = get_pct_zones(region_name)
12 | iow_centroids = get_pct_centroids(region_name)
13 | iow_lines = get_pct_lines(region_name)
14 | iow_routes_fast = get_pct_routes_fast(region_name)
15 | iow_routes_quiet = get_pct_routes_quiet(region_name) # geometry only; cycling potential not available
16 | iow_rnet = get_pct_rnet(region_name)
17 |
18 | # get pct data at MSOA level
19 | iow_zones_msoa = get_pct_zones(region_name, geography = "msoa")
20 | iow_centroids_msoa = get_pct_centroids(region_name, geography = "msoa")
21 | iow_routes_fast_msoa = get_pct_routes_fast(region_name, geography = "msoa")
22 | iow_rnet_msoa = get_pct_rnet(region_name, geography = "msoa")
23 |
24 | # get pct data for travel to schools
25 | iow_zones_school = get_pct_zones(region_name, purpose = "school", geography = "lsoa")
26 | iow_centroids_school_msoa = get_pct_centroids(region_name, purpose = "school", geography = "msoa")
27 | iow_routes_fast_school = get_pct_routes_fast(region_name, purpose = "school")
28 | iow_rnet_school = get_pct_rnet(region_name, purpose = "school")
29 |
30 | # map route network with base-r
31 | plot(iow_rnet)
32 | plot(iow_zones$geometry)
33 | plot(iow_rnet$geometry, col = "green", add = TRUE)
34 |
35 | # map route network with mapview
36 | library(mapview)
37 |
38 | mapview(iow_rnet)
39 | mapview(iow_rnet[, "bicycle"]) # with colour gradient and legend
40 | mapview(iow_centroids) + mapview(iow_rnet[, "bicycle"])
41 |
42 | # map route network with tmap
43 | library(tmap)
44 |
45 | tm_shape(iow_zones) +
46 | tm_polygons(col = "lightblue") +
47 | tm_shape(iow_rnet) +
48 | tm_lines(col = "bicycle", lwd = 2) +
49 | tm_basemap(server = "Esri.WorldTopoMap")
50 |
51 | # compare top desire lines and routes with top route network segments
52 | top_lines = top_n(iow_lines, 20, wt = bicycle)
53 | top_routes_fast = top_n(iow_routes_fast, 20, wt = bicycle)
54 | top_rnet_segments = top_n(iow_rnet, 100, wt = bicycle)
55 |
56 | tm_shape(top_lines) +
57 | tm_lines(col = "bicycle", lwd = 2)
58 |
59 | top_routes_fast = arrange(top_routes_fast, bicycle)
60 | tm_shape(top_routes_fast) +
61 | tm_lines(col = "bicycle", lwd = 2)
62 |
63 | tm_shape(top_rnet_segments) +
64 | tm_lines(col = "bicycle", lwd = 2)
65 |
66 | # look at different PCT cycling uptake scenarios
67 | tm_shape(iow_rnet) +
68 | tm_lines(col = "dutch_slc", lwd = 2)
69 |
70 | tm_shape(iow_zones_msoa) +
71 | tm_polygons(col = "ebike_slc")
72 |
73 | tm_shape(iow_rnet_school) +
74 | tm_lines(col = "cambridge_slc", lwd = 2)
75 |
76 | # try out different colour palettes
77 | install.packages("tmaptools") # in case the package is not already installed
78 | tmaptools::palette_explorer()
79 |
80 | tm_shape(top_rnet_segments) +
81 | tm_lines(col = "bicycle", lwd = 2, palette = "viridis")
82 |
83 |
84 | # Exercises ---------------------------------------------------------------
85 |
86 | # 1) Find the name of the PCT region for an area of your choice. Download the following data for that region and map them using either mapview or tmap
87 | # - MSOA zones
88 | # - MSOA fast routes (travel to work)
89 | # - MSOA route network (travel to work)
90 |
91 | # 2) Identify the top 10 MSOA to MSOA routes in your region (according to 2011 cycling levels), and map them using tmap. What is the mean percentage increase in cycling on these routes, when comparing the Go Dutch scenario with 2011 cycling levels?
92 |
93 | # 3) According to both 2011 cycling levels and the Go Dutch scenario, which zone has the largest number of cyclists? Which has the largest proportion of cyclists?
94 |
95 |
--------------------------------------------------------------------------------
/inst/pct-wy.R:
--------------------------------------------------------------------------------
1 | # Show PCT data
2 |
3 | library(pct)
4 | library(stplanr)
5 | library(tmap)
6 | library(dplyr)
7 | tmap_mode("view")
8 |
9 | centroids = get_centroids_ew()
10 | plot(centroids$geometry)
11 |
12 | wy = pct_regions[pct_regions$region_name == "west-yorkshire", ]
13 | tm_shape(wy) + tm_polygons()
14 |
15 | centroids = st_transform(centroids, st_crs(wy))
16 | centroids_wy = centroids[wy, ]
17 | plot(centroids_wy)
18 |
19 | od = get_od()
20 |
21 | head(od$geo_code1)
22 | head(centroids$msoa11cd)
23 |
24 | od_wy = od[od$geo_code1 %in% centroids_wy$msoa11cd, ]
25 | od_wy_ew = od_wy[od_wy$geo_code2 %in% centroids$msoa11cd, ]
26 |
27 | od_wy_ew_top = od_wy_ew %>%
28 | filter(all > 50)
29 |
30 | lines_wy_top = od2line(od_wy_ew_top, centroids)
31 | plot(lines_wy_top)
32 |
33 | tm_shape(wy) + tm_polygons() +
34 | tm_shape(lines_wy_top) + tm_lines()
35 |
36 | r = line2route(lines_wy_top[8, ], plan = "quietest")
37 | tm_shape(r) + tm_lines()
38 |
39 | # assignment --------------------------------------------------------------
40 |
41 | system.time(r = line2route(lines_wy_top[8, ], plan = "quietest"))
42 | system.time(r <- line2route(lines_wy_top[8, ], plan = "quietest"))
43 | system.time({r = line2route(lines_wy_top[8, ], plan = "quietest")})
44 |
45 | # comparison with infrastructure data
46 |
47 | library(osmdata)
48 | leeds_ring_road = opq("leeds") %>%
49 | add_osm_feature(key = "name", value = "Leeds Inner Ring Road") %>%
50 | osmdata_sf()
51 | lrr_points = leeds_ring_road$osm_points %>% st_transform(27700)
52 | lrr_lines = leeds_ring_road$osm_lines %>% st_transform(27700)
53 | lrr_mline = leeds_ring_road$osm_multilines %>% st_transform(27700)
54 | # qtm(lrr_lines) # looks good, with some gaps
55 | # qtm(lrr_mline)
56 | lrr_buff = lrr_lines %>%
57 | st_buffer(30) %>%
58 | st_union()
59 | # qtm(lrr_buff)
60 | lrr_buff_pol = smoothr::fill_holes(lrr_buff, 1e9)
61 | lrr_concave = concaveman::concaveman(points = lrr_points, concavity = 2)
62 | lrr_concave_10 = concaveman::concaveman(points = lrr_points, concavity = 10)
63 |
64 | # qtm(lrr_concave) # works very well...
65 | lrr_30 = lrr_concave_10 %>%
66 | st_buffer(30)
67 | lrr_100 = lrr_concave_10 %>%
68 | st_buffer(100)
69 | # qtm(lrr_100)
70 | tm_shape(lrr_100) +
71 | tm_polygons(col = "blue", alpha = 0.05, border.col = "blue") +
72 | tm_shape(lrr_buff_pol) +
73 | tm_polygons(col = "red", alpha = 0.05, border.col = "red") +
74 | tm_shape(lrr_lines) +
75 | tm_lines() +
76 | tm_scale_bar()
77 |
78 | lrr = st_transform(lrr_30, st_crs(centroids_wy))
79 | centroid_lcc = centroids_wy[lrr, ]
80 |
81 | lines_wy_top$dist_km = as.numeric(st_length(lines_wy_top) / 1000)
82 | lines_wy_top_5km = lines_wy_top %>% filter(dist_km <= 5)
83 | lines = lines_wy_top_5km[lrr, ] %>% filter(geo_code1 != geo_code2)
84 | routes = line2route(lines)
85 | plot(routes$geometry)
86 |
87 | routes = st_sf(
88 | cbind(st_drop_geometry(routes), st_drop_geometry(lines)),
89 | geometry = routes$geometry
90 | )
91 |
92 | pcycle_dutch = uptake_pct_godutch(
93 | distance = routes$length,
94 | gradient = routes$av_incline
95 | )
96 |
97 | plot(routes$dist_km, pcycle_dutch)
98 |
99 | routes$pcycle_godutch = pcycle_dutch
100 | routes$bicycle_dutch = pcycle_dutch * routes$all + routes$bicycle
101 |
102 | rnet = overline2(routes, "bicycle_dutch")
103 | plot(rnet)
104 |
105 | tm_shape(rnet) + tm_lines(lwd = "bicycle_dutch", scale = 9)
106 |
107 | existing = read_sf("https://github.com/ITSLeeds/pct/releases/download/0.2.4/inst.2frmd.2fexisting.geojson")
108 |
109 | tm_shape(existing) + tm_lines()
110 |
111 | # existing_buff = geo_buffer(existing, 100)
112 | existing_buff = existing %>%
113 | st_transform(27700) %>%
114 | st_buffer(100) %>%
115 | st_transform(4326) %>%
116 | st_union()
117 |
118 | rnet_infra = st_intersection(rnet, existing_buff)
119 | plot(rnet_infra$geometry)
120 |
121 | rnet_infra = st_difference(rnet, existing_buff)
122 |
123 | tm_shape(existing_buff) + tm_polygons() +
124 | tm_shape(rnet_infra) +
125 | tm_lines(lwd = "bicycle_dutch", scale = 9)
126 |
--------------------------------------------------------------------------------
/inst/pct_training_solutions.Rmd:
--------------------------------------------------------------------------------
1 |
2 | ---
3 | title: "Propensity to Cycle Tool Training course"
4 | output: rmarkdown::html_vignette
5 | vignette: >
6 | %\VignetteIndexEntry{pct_training}
7 | %\VignetteEngine{knitr::rmarkdown}
8 | %\VignetteEncoding{UTF-8}
9 | bibliography: ../vignettes/refs_training.bib
10 | ---
11 |
12 | ```{r, include = FALSE}
13 | knitr::opts_chunk$set(
14 | collapse = TRUE,
15 | comment = "#>",
16 | out.width = "50%"
17 | )
18 | ```
19 |
20 | ```{r, eval=FALSE, echo=FALSE}
21 | # get citations
22 | refs = RefManageR::ReadZotero(group = "418217", .params = list(collection = "JFR868KJ", limit = 100))
23 | refs2 = RefManageR::ReadBib("vignettes/refs.bib")
24 | refs = c(refs, refs2)
25 | citr::insert_citation(bib_file = "vignettes/refs_training.bib")
26 | RefManageR::WriteBib(refs, "vignettes/refs_training.bib")
27 | citr::tidy_bib_file(rmd_file = "vignettes/pct_training.Rmd", messy_bibliography = "vignettes/refs_training.bib")
28 | ```
29 |
30 | These solutions assume you have worked through the exercises in the [`pct_training` vignette](https://itsleeds.github.io/pct/articles/pct_training.html) and have loaded the necessary packages.
31 |
32 | ```{r, results='hide', eval=FALSE}
33 | library(pct)
34 | library(dplyr) # in the tidyverse
35 | library(tmap) # installed alongside mapvew
36 | ```
37 |
38 |
39 | ## Getting and viewing PCT data
40 |
41 | - G1: Using the PCT's online interface, hosted at [www.pct.bike/m/?r=isle-of-wight](https://www.pct.bike/m/?r=isle-of-wight), identify the MSOA **zone** that has the highest number of people who cycle to work.
42 |
43 | Answer: E02003582 Isle of Wight 002
44 |
45 | - G2: Using data downloaded with the command `get_pct_zones()`, identify the zone that has highest level of cycling with the function `top_n()` and save the result as an object called `z_highest_cycling` (hint: you may want to start by 'cleaning' the data you have downloaded to include only a few key columns with the function `select()`, as follows):
46 |
47 | ```{r, eval=FALSE}
48 | library(pct)
49 | library(dplyr) # suggestion: use library(tidyverse)
50 | z_original = get_pct_zones("isle-of-wight")
51 | z = z_original %>%
52 | select(geo_code, geo_name, all, bicycle, car_driver)
53 | ```
54 |
55 | ```{r, echo=TRUE, , eval=FALSE}
56 | # the solution:
57 | z_highest_cycling = z %>%
58 | top_n(n = 1, wt = bicycle)
59 | ```
60 |
61 | Answer: E02003582 Isle of Wight 002, check by viewing the data frame or using `print()`
62 |
63 | - G3: Use the `plot()` command to visualise where on the Ilse of Wight this 'high cycling' zone is (hint: you will need to use the `plot()` function twice, once to plot `z$geometry`, and again with the argument `add = TURE` and a `col` argument to add the layer on top of the base layer and give it a colour).
64 | The result should look something like something this:
65 |
66 | ```{r, echo=TRUE, eval=FALSE}
67 | plot(z$geometry)
68 | plot(z_highest_cycling$geometry, col = "red", add = TRUE)
69 | ```
70 |
71 | - G4: Using the online interface, identify the top 5 MSOA to MSOA **desire lines** that have the highest number of people who cycle to work.
72 |
73 | Answer:
74 |
75 | E02003588 E02003591 654
76 |
77 | E02003588 E02003589 615
78 |
79 | E02003582 E02003588 567
80 |
81 | E02003581 E02003588 485
82 |
83 | E02003585 E02003588 406
84 |
85 |
86 | - G5: Using the function `get_pct_lines()`, identify the top 5 MSOA to MSOA **desire lines** that have the highest number of people who cycle to work (hint: you might want to start with the code shown below).
87 | - Bonus: also find the 5 desire lines with the highest number of people driving to work. Plot them and find the straight line distance of these lines with the function `st_distance()`.
88 |
89 | ```{r get routes, eval=FALSE}
90 | # Aim: get top 5 cycle routes
91 | l_original_msoa = get_pct_lines("isle-of-wight")
92 | l_msoa = l_original_msoa %>%
93 | select(geo_code1, geo_code2, all, bicycle, car_driver, rf_avslope_perc, rf_dist_km)
94 | ```
95 |
96 | ```{r, echo=TRUE, warning=FALSE, fig.show='hold', fig.cap="Top 5 MSOA to MSOA desire lines with highest number of people cycling (left) and driving (right) in the Isle of Wight.", eval = FALSE}
97 |
98 | l = l_msoa
99 | l_top_cycling = l %>%
100 | top_n(n = 5, wt = bicycle)
101 | plot(z$geometry)
102 | plot(l_top_cycling, add = TRUE, lwd = 5, col = "green")
103 |
104 | # top 5 driving routes
105 | l_top_driving = l %>%
106 | top_n(n = 5, wt = car_driver)
107 | plot(z$geometry)
108 | plot(l_top_driving, add = TRUE, lwd = 5, col = "red")
109 |
110 | ```
111 |
112 | - G6 (Bonus): Repeat the exercise but for LSOA to LSOA desire lines (by setting the argument `geography = "lsoa"`, remember to change the names of the objects you create). The results should look something like this:
113 |
114 | ```{r, echo=TRUE, warning=FALSE, fig.show='hold', fig.cap="Top 5 LSOA-LSOA desire lines with highest number of people cycling (left) and driving (right) in the Isle of Wight.", eval=FALSE}
115 | # at the lsoa level
116 | l_original_lsoa = get_pct_lines("isle-of-wight", geography = "lsoa")
117 | l = l_original_lsoa %>%
118 | select(geo_code1, geo_code2, all, bicycle, car_driver)
119 | l_top_cycling = l %>%
120 | top_n(n = 5, wt = bicycle)
121 | plot(z$geometry)
122 | plot(l_top_cycling, add = TRUE, lwd = 5, col = "green")
123 |
124 | # top 5 driving routes
125 | l_top_driving = l %>%
126 | top_n(n = 5, wt = car_driver)
127 | plot(z$geometry)
128 | plot(l_top_driving, add = TRUE, lwd = 5, col = "red")
129 | ```
130 |
131 | - G7: Why are the results different? What are the advantages and disadvantages of using smaller zones, as represented by the LSOA data above?
132 |
133 | Answer: LSOAs are samller than MSOAs, so provide more spatial detail. This can be useful. However MSOAs often give a better overview. For example MSOA anlaysis will highlight commuter travel to a single to a city centre. LSOA travel is often more chaotic with many origins and desinations.
134 |
135 | As LSOAs are smaller they are more susetible to bias from outlieres, conisder how many people need to change behavoir for a 1% mode shift for and LSOA and MSOA.
136 |
137 | - G8 (bonus): do the same analysis but with the top **300** routes cycled and driven. Hint: set the line width with `lwd = l_top_cycling$bicycle / mean(l_top_cycling$bicycle)` to portray the relative importance of each route.
138 |
139 | ```{r, echo=TRUE, warning=FALSE, fig.show='hold', fig.cap="Top 300 LSOA-LSOA desire lines with highest number of people cycling (left) and driving (right) in the Isle of Wight.", eval=FALSE}
140 | # at the lsoa level
141 | l_top_cycling = l %>%
142 | top_n(n = 300, wt = bicycle)
143 | plot(z$geometry)
144 | plot(l_top_cycling, add = TRUE, lwd = l_top_cycling$bicycle / mean(l_top_cycling$bicycle), col = "green")
145 |
146 | # top 5 driving routes
147 | l_top_driving = l %>%
148 | top_n(n = 300, wt = car_driver)
149 | plot(z$geometry)
150 | plot(l_top_driving, add = TRUE, lwd = l_top_driving$car_driver / mean(l_top_driving$car_driver), col = "red")
151 | ```
152 |
153 | ## Modifying PCT data to identify routes/roads of interest
154 |
155 | - M1: Building on the example above, add a new column called `pcycle` to the object `l_msoa` that contains the % who cycle to work (hint: you might want to start this by typing `l_msoa$pcycle = ...`) and plot the results (shown in left hand panel in plot below).
156 |
157 | ```{r p2, eval=FALSE}
158 | l_msoa$pcycle = l_msoa$bicycle / l_msoa$all * 100
159 | plot(l_msoa["pcycle"], lwd = l_msoa$all / mean(l_msoa$all), breaks = c(0, 5, 10, 20, 50))
160 | ```
161 |
162 | - M2 (bonus): identify road segments with the highest estimated number of people cycling currently, and under the Go Dutch scenario (hint: you can download the route network with `get_pct_rnet("isle-of-wight")`)
163 |
164 | ```{r eval=FALSE, echo=TRUE}
165 | rnet = get_pct_rnet("isle-of-wight")
166 | ```
167 |
168 | ## Scenarios of change
169 |
170 | - S1: Generate a 'Go Dutch' scenario for the Isle of Wight using the function `uptake_pct_godutch()` (hint: the following code chunk will create a 'Government Target' scenario):
171 |
172 | ```{r, eval=FALSE}
173 | l_msoa$euclidean_distance = as.numeric(sf::st_length(l_msoa))
174 | l_msoa$pcycle_govtarget = uptake_pct_govtarget(
175 | distance = l_msoa$rf_dist_km,
176 | gradient = l_msoa$rf_avslope_perc
177 | ) * 100 + l_msoa$pcycle
178 | ```
179 |
180 | ```{r change, echo=TRUE, eval=FALSE}
181 | l_msoa$pcycle_dutch = uptake_pct_godutch(
182 | distance = l_msoa$rf_dist_km,
183 | gradient = l_msoa$rf_avslope_perc
184 | ) * 100 + l_msoa$pcycle
185 | ```
186 |
187 | ```{r dutch_pcycle, echo=TRUE, warning=FALSE, fig.show='hold', fig.cap="Percent cycling currently (left) and under a 'Go Dutch' scenario (right) in the Isle of Wight.", eval=FALSE}
188 | plot(l_msoa["pcycle"], lwd = l_msoa$all / mean(l_msoa$all), breaks = c(0, 5, 10, 20, 50))
189 | plot(l_msoa["pcycle_dutch"], lwd = l_msoa$all / mean(l_msoa$all), breaks = c(0, 5, 10, 20, 50))
190 | ```
191 |
192 | - S2: Think of alternative scenarios that would be useful for your work
193 | - S3 (bonus): look inside the function [`pct_uptake_godutch()`](https://github.com/ITSLeeds/pct/blob/master/R/uptake.R#L36) - how could it be modified?
194 |
195 | ## Routing
196 |
197 | - R1: Using the function `route_osrm()` find the route associated with the most cycled desire line in the Isle of Wight. The result should look similar to that displayed in the map below (hint: you may want to start your answer with the following lines of code - **warning: the function may need to run a few times before it works**):
198 |
199 | ```{r, eval=FALSE}
200 | library(stplanr)
201 | l_top = l_msoa %>%
202 | top_n(n = 1, wt = bicycle)
203 | ```
204 |
205 | ```{r, eval=FALSE, echo=TRUE}
206 | r_top = stplanr::route_osrm(l_top)
207 | sf::write_sf(sf::st_as_sf(r_top), "r_top.geojson")
208 | piggyback::pb_upload("r_top.geojson")
209 | piggyback::pb_download_url()
210 | ```
211 |
212 | ```{r, echo=TRUE, eval=FALSE}
213 | r_top = sf::read_sf("https://github.com/ITSLeeds/pct/releases/download/0.0.1/r_top.geojson")
214 | tm_shape(r_top) +
215 | tm_lines(lwd = 5)
216 | ```
217 |
218 | - R2: What are the problems associated with this route from a cycling perspective? Take a look at the help page opened by entering `?route_osrm` to identify the reason why the route is not particularly useful from a cycling perspective.
219 |
220 | - R3: Regenerate the route using the function `line2route()`. What is the difference in the length between each route, and what other differences can you spot? **Note: this exercise requires an API Key from CycleStreets.net.**
221 |
222 | ```{r, echo=TRUE, eval=FALSE}
223 | r_cs = stplanr::line2route(l_top)
224 | leaflet() %>%
225 | addTiles() %>%
226 | addPolylines(data = r_cs)
227 | ```
228 |
229 | - R4 (bonus): what features of a routing service would be most useful for your work and why?
230 |
231 | ## Route networks
232 |
233 | - RN1: Generate a 'route network' showing number of people walking in the top 30 routes in the Isle of Wight, allocated to the transport network (hint: use the `overline2()` function and begin the script as follows, the results should look similar to the results below):
234 |
235 | ```{r, eval=FALSE}
236 | route_data = sf::st_sf(wight_lines_30, geometry = wight_routes_30$geometry)
237 | ```
238 |
239 | ```{r, echo=TRUE, message=FALSE, eval=FALSE}
240 | rnet_walk = overline2(x = route_data, "foot")
241 | tm_shape(rnet_walk) +
242 | tm_lines(lwd = "foot", scale = 9)
243 | ```
244 |
245 | ```{r, echo=TRUE, eval=FALSE}
246 | # Demo PCT Analysis#
247 | # Make a commuting quiet route network for Isle of Wight
248 | # and combine it with the travle to school route network
249 |
250 | # Step 1: Load Library
251 | library(tidyverse)
252 | library(sf)
253 | library(pct)
254 | library(stplanr)
255 |
256 | # Step 2: Get Data
257 | routes_commute = get_pct_routes_quiet(region = "isle-of-wight",
258 | purpose = "commute",
259 | geography = "lsoa")
260 |
261 | lines_commute = get_pct_lines(region = "isle-of-wight",
262 | purpose = "commute",
263 | geography = "lsoa")
264 |
265 | rnet_school = get_pct_rnet(region = "isle-of-wight",
266 | purpose = "school",
267 | geography = "lsoa")
268 |
269 | # Step 3: Prepare Data
270 | lines_commute = lines_commute %>%
271 | st_drop_geometry() %>%
272 | select(id, bicycle, dutch_slc)
273 |
274 | routes_commute = routes_commute %>%
275 | select(id)
276 |
277 | # Join Cycling Levels to Routes
278 | routes_commute = left_join(routes_commute, lines_commute)
279 | plot(routes_commute["bicycle"])
280 |
281 | # Make a commuting Rnet
282 | rnet_commute = overline2(routes_commute,
283 | attrib = c("bicycle","dutch_slc"))
284 | plot(rnet_commute["bicycle"])
285 |
286 | # Combine commuting and travel to schools
287 | rnet_school <- rnet_school %>%
288 | select(dutch_slc)
289 | rnet_commute <- rnet_commute %>%
290 | select(dutch_slc)
291 | rnet_commute$bicycle <- NULL
292 |
293 |
294 | rnet_both = rbind(rnet_commute, rnet_school)
295 | rnet_both = overline2(rnet_both,
296 | attrib = c("dutch_slc"))
297 | mapview::mapview(rnet_both, at = c(50,100,200,500,1000))
298 |
299 | ```
300 |
301 |
302 |
--------------------------------------------------------------------------------
/inst/rapid-geojson-download.R:
--------------------------------------------------------------------------------
1 |
2 | # Download and map data from Rapid Cycleway Prioritisation Tool -----------
3 |
4 | # select URLS
5 | west_of_england_existing_url = "https://www.cyipt.bike/rapid/west-of-england/cycleways.geojson"
6 | west_of_england_cohesive_url = "https://www.cyipt.bike/rapid/west-of-england/cohesive_network.geojson"
7 | west_of_england_top_url = "https://www.cyipt.bike/rapid/west-of-england/top_routes.geojson"
8 | west_of_england_spare_url = "https://www.cyipt.bike/rapid/west-of-england/spare_lanes.geojson"
9 | west_of_england_wide_url = "https://www.cyipt.bike/rapid/west-of-england/wide_lanes.geojson"
10 | north_somerset_top_url = "https://www.cyipt.bike/rapid/north-somerset/top_routes.geojson"
11 |
12 | rapid_urls = c(west_of_england_existing_url, west_of_england_cohesive_url, west_of_england_top_url, west_of_england_spare_url, west_of_england_wide_url, north_somerset_top_url)
13 |
14 | # create new directory
15 | dir.create("data/rapid-data")
16 |
17 | # assign file names and paths
18 | rapid_file_names = file.path("data/rapid-data", paste(substring(dirname(rapid_urls),30), basename(rapid_urls), sep = "_"))
19 |
20 | # download files
21 | download.file(url = rapid_urls, destfile = rapid_file_names)
22 |
23 | # read one file at a time
24 | library(sf)
25 | west_of_england_cycleways = read_sf("data/rapid-data/west-of-england_cycleways.geojson")
26 | west_of_england_cohesive_network = read_sf("data/rapid-data/west-of-england_cohesive_network.geojson")
27 |
28 | # read all files in directory
29 | library(sf)
30 | library(stringr)
31 |
32 | file_path = "data/rapid-data/"
33 | files_wanted = list.files(file_path)
34 |
35 | files_wanted %>%
36 | purrr::map(function(file_name){
37 | assign(x = gsub("-", "_", str_remove(file_name, ".geojson")),
38 | value = read_sf(paste0(file_path, file_name)),
39 | envir = .GlobalEnv)
40 | })
41 |
42 | # set up basemaps
43 | s = c(
44 | `Grey basemap` = "CartoDB.Positron",
45 | `Coloured basemap` = "Esri.WorldTopoMap",
46 | `OSM existing cycle provision (CyclOSM)` = "https://b.tile-cyclosm.openstreetmap.fr/cyclosm/{z}/{x}/{y}.png",
47 | `PCT commuting, Government Target` = "https://npttile.vs.mythic-beasts.com/commute/v2/govtarget/{z}/{x}/{y}.png",
48 | `PCT schools, Government Target` = "https://npttile.vs.mythic-beasts.com/school/v2/govtarget/{z}/{x}/{y}.png",
49 | `Satellite image` = "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}'"
50 | )
51 | tms = c(FALSE, FALSE, FALSE, TRUE, TRUE, FALSE)
52 | # Find other basemaps at https://leaflet-extras.github.io/leaflet-providers/preview/
53 |
54 | # create map
55 | library(tmap)
56 | tmap_mode("view")
57 |
58 | tm_shape(west_of_england_cohesive_network) +
59 | tm_lines(col = "#9077AD", lwd = 5) +
60 | tm_shape(west_of_england_spare_lanes) +
61 | tm_lines(col = "#B91F48", lwd = 3) +
62 | tm_shape(west_of_england_wide_lanes) +
63 | tm_lines(col = "#FF7F00", lwd = 3) +
64 | tm_shape(west_of_england_top_routes) +
65 | tm_lines(col = "blue", lwd = 3) +
66 | tm_shape(west_of_england_cycleways) +
67 | tm_lines(col = "darkgreen", lwd = 1.3) +
68 | tm_basemap(server = s, tms = tms)
69 |
70 |
--------------------------------------------------------------------------------
/inst/test-setup.R:
--------------------------------------------------------------------------------
1 | # Aim: test set-up for PCT training course
2 |
3 | # test you can install packages
4 | install.packages("remotes", quiet = TRUE)
5 |
6 | # test you have the right packages installed
7 | pkgs = c("sf", "stplanr", "pct", "tmap", "dplyr")
8 | remotes::install_cran(pkgs, quiet = TRUE)
9 |
10 | # test you can read-in csv files:
11 | od_data = read.csv("https://github.com/npct/pct-outputs-regional-notR/raw/master/commute/msoa/avon/od_attributes.csv")
12 | head(od_data)
13 | od_data$pcycle = od_data$bicycle / od_data$all
14 | plot(od_data$rf_dist_km, od_data$pcycle, cex = od_data$all / mean(od_data$all))
15 |
16 | # test the sf package: read-in and download zones and centroids
17 | library(sf)
18 | u1 = "https://github.com/npct/pct-outputs-regional-notR/raw/master/commute/msoa/avon/c.geojson"
19 | u1b = "https://github.com/npct/pct-outputs-regional-notR/raw/master/commute/msoa/avon/z.geojson"
20 | centroids = read_sf(u1)
21 | districts = read_sf(u1b)
22 | plot(districts$geometry)
23 | centroids_geo = st_centroid(districts)
24 | plot(centroids$geometry, add = TRUE)
25 | plot(centroids_geo$geometry, add = TRUE, col = "red")
26 |
27 | # check interactive mapping with tmap
28 | library(tmap)
29 | tmap_mode("view")
30 | u2 = "https://github.com/npct/pct-outputs-regional-notR/raw/master/commute/msoa/avon/l.geojson"
31 | desire_lines = sf::read_sf(u2)
32 | desire_lines_subset = desire_lines[desire_lines$all > 100, ]
33 | tm_shape(desire_lines_subset) +
34 | tm_lines(col = "bicycle", palette = "viridis", lwd = "all", scale = 9)
35 |
36 | # check route network generation with stplanr
37 | library(stplanr)
38 | u3 = "https://github.com/npct/pct-outputs-regional-notR/raw/master/commute/msoa/avon/rf.geojson"
39 | routes = sf::read_sf(u3)
40 | library(dplyr)
41 | routes_1 = routes %>%
42 | slice(which.max(bicycle))
43 | tm_shape(routes_1) +
44 | tm_lines()
45 | rnet = overline(routes, "bicycle")
46 | b = c(0, 0.5, 1, 2, 3, 8) * 1e3
47 | tm_shape(rnet) +
48 | tm_lines(scale = 2, col = "bicycle", palette = "viridis", breaks = b)
49 |
50 | # check analysis with dplyr and estimation of cycling uptake with pct function
51 | library(pct)
52 |
53 | routes$Potential = pct::uptake_pct_godutch(
54 | distance = routes$rf_dist_km,
55 | gradient = routes$rf_avslope_perc
56 | ) *
57 | routes$all
58 | rnet_potential = overline(routes, "Potential")
59 | tm_shape(rnet_potential) +
60 | tm_lines(lwd = "Potential", scale = 9, col = "Potential", palette = "viridis", breaks = b)
61 |
62 | # Uncomment this line to get the mean cycling potential of route segments in Bristol
63 | # round(mean(rnet_potential$Potential))
64 |
65 | # generate output report
66 | # knitr::spin(hair = "code/reproducible-example.R")
67 |
68 | # # to convert OD data into desire lines with the od package you can uncomment the following lines
69 | # # system.time({
70 | # test_desire_lines1 = stplanr::od2line(od_data, centroids)
71 | # # })
72 | # # system.time({
73 | # test_desire_lines2 = od::od_to_sf(x = od_data, z = centroids)
74 | # # })
75 | # plot(test_desire_lines2)
76 |
77 | # test routing on a single line (optional - uncomment to test this)
78 | # warning you can only get a small number, e.g. 5, routes before this stops working!
79 | # library(osrm)
80 | # single_route = route(l = desire_lines[1, ], route_fun = osrm::osrmRoute, returnclass = "sf")
81 | # mapview::mapview(desire_lines[1, ]) +
82 | # mapview::mapview(single_route)
83 | # see https://cran.r-project.org/package=cyclestreets and other routing services
84 | # for other route options, e.g. https://github.com/ropensci/opentripplanner
85 |
--------------------------------------------------------------------------------
/inst/uptake-model.R:
--------------------------------------------------------------------------------
1 |
2 |
3 | library(pct)
4 | library(tidyverse)
5 |
6 | l = get_pct_lines("south-yorkshire")
7 | l$pcycle = l$bicycle / l$all
8 | plot(l$rf_dist_km, l$pcycle)
9 | ggplot(l) + geom_point(aes(rf_dist_km, pcycle, alpha = all))
10 | l$distance_groups = cut(l$rf_dist_km, breaks = seq(from = 0, to = 20, by = 1))
11 | head(l$distance_groups)
12 | l_grouped = l %>%
13 | sf::st_drop_geometry() %>%
14 | group_by(dist_band = as.character(distance_groups)) %>%
15 | summarise(
16 | distance = mean(rf_dist_km),
17 | all = sum(all), bicycle = sum(bicycle),
18 | hilliness = mean(l$rf_avslope_perc)
19 | )
20 |
21 | ggplot(l_grouped) +
22 | geom_point(aes(distance, all)) +
23 | geom_point(aes(distance, bicycle))
24 |
25 | l_grouped = l %>%
26 | sf::st_drop_geometry() %>%
27 | group_by(dist_band = as.character(distance_groups)) %>%
28 | summarise(
29 | distance = mean(rf_dist_km),
30 | pcycle = sum(bicycle)/ sum(all),
31 | hilliness = mean(l$rf_avslope_perc)
32 | )
33 |
34 | ggplot(l_grouped) +
35 | geom_point(aes(distance, pcycle))
36 |
37 | l_grouped$baseline = pct::uptake_pct_govtarget(
38 | distance = l_grouped$distance,
39 | gradient = rep(0, nrow(l_grouped))
40 | ) / 2
41 |
42 | ggplot(l_grouped) +
43 | geom_point(aes(distance, baseline)) +
44 | geom_point(aes(distance, pcycle)) +
45 | ylim(c(0, 0.10))
46 |
47 |
48 | l_grouped$logit_pcycle = boot::logit(l_grouped$pcycle)
49 | ggplot(l_grouped) +
50 | geom_point(aes(distance, logit_pcycle))
51 |
52 | m = lm(logit_pcycle ~ distance, hilliness, data = l_grouped)
53 | ggplot(l_grouped) +
54 | geom_point(aes(distance, pcycle)) +
55 | geom_point(aes(distance, boot::inv.logit(m$fitted.values)), col = "grey")
56 |
57 |
58 | # cid data ----------------------------------------------------------------
59 |
60 | library(CycleInfraLnd)
61 | points = get_cid_points(type = "traffic_calming")
62 |
63 |
--------------------------------------------------------------------------------
/man/desire_lines_leeds.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \name{desire_lines_leeds}
5 | \alias{desire_lines_leeds}
6 | \title{Cycle route desire lines for Leeds}
7 | \description{
8 | Cycle route desire lines for Leeds
9 | }
10 | \examples{
11 | # see data-raw folder for generation code
12 | desire_lines_leeds
13 | }
14 | \keyword{datasets}
15 |
--------------------------------------------------------------------------------
/man/figures/README-centroids-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/man/figures/README-centroids-1.png
--------------------------------------------------------------------------------
/man/figures/README-decay-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/man/figures/README-decay-1.png
--------------------------------------------------------------------------------
/man/figures/README-decayhills-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/man/figures/README-decayhills-1.png
--------------------------------------------------------------------------------
/man/figures/README-desire-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/man/figures/README-desire-1.png
--------------------------------------------------------------------------------
/man/figures/README-get_pct_lines-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/man/figures/README-get_pct_lines-1.png
--------------------------------------------------------------------------------
/man/figures/README-rnetgove-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/man/figures/README-rnetgove-1.png
--------------------------------------------------------------------------------
/man/figures/README-routes_fast-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/man/figures/README-routes_fast-1.png
--------------------------------------------------------------------------------
/man/figures/README-routes_vital-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/man/figures/README-routes_vital-1.png
--------------------------------------------------------------------------------
/man/get_centroids_ew.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/msoa_centroids.R
3 | \name{get_centroids_ew}
4 | \alias{get_centroids_ew}
5 | \title{Download MSOA centroids for England and Wales}
6 | \usage{
7 | get_centroids_ew()
8 | }
9 | \description{
10 | Downloads and processes data on where people live in England and Wales.
11 | See \href{https://geoportal.statistics.gov.uk/datasets/b0a6d8a3dc5d4718b3fd62c548d60f81_0}{geoportal.statistics.gov.uk}.
12 | }
13 |
--------------------------------------------------------------------------------
/man/get_desire_lines.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/desire_lines.R
3 | \name{get_desire_lines}
4 | \alias{get_desire_lines}
5 | \title{Desire lines}
6 | \usage{
7 | get_desire_lines(region = NULL, n = NULL, omit_intrazonal = FALSE)
8 | }
9 | \arguments{
10 | \item{region}{The PCT region or local authority to download data from (e.g. \code{west-yorkshire} or \code{Leeds}).
11 | See \code{View(pct_regions_lookup)} for a full list of possible region names.}
12 |
13 | \item{n}{top n number of destinations with most trips in the 2011 census
14 | within the \code{region}.}
15 |
16 | \item{omit_intrazonal}{should intrazonal OD pairs be omited from result?
17 | \code{FALSE} by default.}
18 | }
19 | \description{
20 | This function generates "desire lines" from census 2011 data.
21 | By default gets all desire lines from census in region, but
22 | can get the top \code{n}.
23 | }
24 | \examples{
25 | \donttest{
26 | if(curl::has_internet()) {
27 | desire_lines = get_desire_lines("wight")
28 | plot(desire_lines)
29 | intra_zonal = desire_lines$geo_code1 == desire_lines$geo_code2
30 | plot(desire_lines[intra_zonal, ])
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/man/get_od.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/desire_lines.R
3 | \name{get_od}
4 | \alias{get_od}
5 | \title{Get origin destination data from the 2011 Census}
6 | \usage{
7 | get_od(
8 | region = NULL,
9 | n = NULL,
10 | type = "within",
11 | omit_intrazonal = FALSE,
12 | base_url = paste0("https://s3-eu-west-1.amazonaws.com/",
13 | "statistics.digitalresources.jisc.ac.uk", "/dkan/files/FLOW/"),
14 | filename = "wu03ew_v2",
15 | u = NULL
16 | )
17 | }
18 | \arguments{
19 | \item{region}{The PCT region or local authority to download data from (e.g. \code{west-yorkshire} or \code{Leeds}).
20 | See \code{View(pct_regions_lookup)} for a full list of possible region names.}
21 |
22 | \item{n}{top n number of destinations with most trips in the 2011 census
23 | within the \code{region}.}
24 |
25 | \item{type}{the type of subsetting: one of \code{from}, \code{to} or \code{within}, specifying how
26 | the od dataset should be subset in relation to the \code{region}.}
27 |
28 | \item{omit_intrazonal}{should intrazonal OD pairs be omited from result?
29 | \code{FALSE} by default.}
30 |
31 | \item{base_url}{the base url where the OD dataset is stored}
32 |
33 | \item{filename}{the name of the file to download, if not the default MSOA level
34 | data.}
35 |
36 | \item{u}{full url of file to download}
37 | }
38 | \description{
39 | This function downloads a .csv file representing movement
40 | between MSOA zones in England and Wales.
41 | By default it returns national data, but
42 | \code{region} can be set to subset the output to a specific
43 | local authority or region.
44 | }
45 | \details{
46 | OD datasets available include wu03uk_v3
47 | and others listed on the Wicid website.
48 | }
49 | \examples{
50 | \donttest{
51 | get_od("wight", n = 3)
52 | get_od()
53 | get_od(filename = "wu03uk_v3")
54 | u = "https://www.nomisweb.co.uk/output/census/2011/wf02ew_oa.zip"
55 | # get_od(u = u)
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/man/get_pct.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/get_pct.R
3 | \name{get_pct}
4 | \alias{get_pct}
5 | \title{Generic function to get regional data from the PCT}
6 | \usage{
7 | get_pct(
8 | base_url = "https://github.com/npct/pct-outputs-regional-notR/raw/master",
9 | purpose = "commute",
10 | geography = "lsoa",
11 | region = NULL,
12 | layer = NULL,
13 | extension = ".geojson",
14 | national = FALSE
15 | )
16 | }
17 | \arguments{
18 | \item{base_url}{Where the data is stored.}
19 |
20 | \item{purpose}{Trip purpose (typically \code{school} or \code{commute})}
21 |
22 | \item{geography}{Geographic resolution of outputs, \code{msoa} or \code{lsoa} (the default)}
23 |
24 | \item{region}{The PCT region or local authority to download data from (e.g. \code{west-yorkshire} or \code{Leeds}).
25 | See \code{View(pct_regions_lookup)} for a full list of possible region names.}
26 |
27 | \item{layer}{The PCT layer of interest, \code{z}, \code{c}, \code{l}, \code{rf}, \code{rq} or \code{rnet}
28 | for zones, centroids, desire lines, routes (fast or quiet) and route networks, respectively}
29 |
30 | \item{extension}{The type of file to download (only \code{.geojson} supported at present)}
31 |
32 | \item{national}{Download nationwide data? \code{FALSE} by default}
33 | }
34 | \description{
35 | This function gets data generated for the Propensity to Cycle Tool
36 | project and returns objects in the modern \code{sf} class.
37 | }
38 | \examples{
39 | \dontrun{
40 | rf = get_pct(region = "isle-of-wight", layer = "rf")
41 | names(rf)[1:20]
42 | vars_to_plot = 10:13
43 | plot(rf[vars_to_plot])
44 | z = get_pct(region = "isle-of-wight", layer = "z")
45 | rf = get_pct(region = "west-yorkshire", layer = "rf")
46 | z_all = get_pct(layer = "z", national = TRUE)
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/man/get_pct_centroids.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/get_pct.R
3 | \name{get_pct_centroids}
4 | \alias{get_pct_centroids}
5 | \title{Get centroid results from the PCT}
6 | \usage{
7 | get_pct_centroids(
8 | region = NULL,
9 | purpose = "commute",
10 | geography = "lsoa",
11 | extension = ".geojson"
12 | )
13 | }
14 | \arguments{
15 | \item{region}{The PCT region or local authority to download data from (e.g. \code{west-yorkshire} or \code{Leeds}).
16 | See \code{View(pct_regions_lookup)} for a full list of possible region names.}
17 |
18 | \item{purpose}{Trip purpose (typically \code{school} or \code{commute})}
19 |
20 | \item{geography}{Geographic resolution of outputs, \code{msoa} or \code{lsoa} (the default)}
21 |
22 | \item{extension}{The type of file to download (only \code{.geojson} supported at present)}
23 | }
24 | \description{
25 | Wrapper around \verb{[get_pct()]} that gets centroid data from the PCT.
26 | }
27 | \examples{
28 | \dontrun{
29 | # don't test to reduce build times
30 | c = get_pct_centroids("isle-of-wight")
31 | plot(c)
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/man/get_pct_lines.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/get_pct.R
3 | \name{get_pct_lines}
4 | \alias{get_pct_lines}
5 | \title{Get desire lines results from the PCT}
6 | \usage{
7 | get_pct_lines(
8 | region = NULL,
9 | purpose = "commute",
10 | geography = "lsoa",
11 | extension = ".geojson"
12 | )
13 | }
14 | \arguments{
15 | \item{region}{The PCT region or local authority to download data from (e.g. \code{west-yorkshire} or \code{Leeds}).
16 | See \code{View(pct_regions_lookup)} for a full list of possible region names.}
17 |
18 | \item{purpose}{Trip purpose (typically \code{school} or \code{commute})}
19 |
20 | \item{geography}{Geographic resolution of outputs, \code{msoa} or \code{lsoa} (the default)}
21 |
22 | \item{extension}{The type of file to download (only \code{.geojson} supported at present)}
23 | }
24 | \description{
25 | Wrapper around \verb{[get_pct()]} that gets l (lines) data from the PCT.
26 | }
27 | \examples{
28 | \dontrun{
29 | # don't test to reduce build times
30 | l = get_pct_lines("isle-of-wight")
31 | plot(l)
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/man/get_pct_rnet.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/get_pct.R
3 | \name{get_pct_rnet}
4 | \alias{get_pct_rnet}
5 | \title{Get route network results from the PCT}
6 | \usage{
7 | get_pct_rnet(
8 | region = NULL,
9 | purpose = "commute",
10 | geography = "lsoa",
11 | extension = ".geojson"
12 | )
13 | }
14 | \arguments{
15 | \item{region}{The PCT region or local authority to download data from (e.g. \code{west-yorkshire} or \code{Leeds}).
16 | See \code{View(pct_regions_lookup)} for a full list of possible region names.}
17 |
18 | \item{purpose}{Trip purpose (typically \code{school} or \code{commute})}
19 |
20 | \item{geography}{Geographic resolution of outputs, \code{msoa} or \code{lsoa} (the default)}
21 |
22 | \item{extension}{The type of file to download (only \code{.geojson} supported at present)}
23 | }
24 | \description{
25 | Wrapper around \verb{[get_pct()]} that gets route road network data from the PCT.
26 | }
27 | \examples{
28 | \dontrun{
29 | # don't test to reduce build times
30 | rnet = get_pct_rnet("isle-of-wight")
31 | plot(rnet)
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/man/get_pct_routes_fast.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/get_pct.R
3 | \name{get_pct_routes_fast}
4 | \alias{get_pct_routes_fast}
5 | \title{Get fast road network results from the PCT}
6 | \usage{
7 | get_pct_routes_fast(
8 | region = NULL,
9 | purpose = "commute",
10 | geography = "lsoa",
11 | extension = ".geojson"
12 | )
13 | }
14 | \arguments{
15 | \item{region}{The PCT region or local authority to download data from (e.g. \code{west-yorkshire} or \code{Leeds}).
16 | See \code{View(pct_regions_lookup)} for a full list of possible region names.}
17 |
18 | \item{purpose}{Trip purpose (typically \code{school} or \code{commute})}
19 |
20 | \item{geography}{Geographic resolution of outputs, \code{msoa} or \code{lsoa} (the default)}
21 |
22 | \item{extension}{The type of file to download (only \code{.geojson} supported at present)}
23 | }
24 | \description{
25 | Wrapper around \verb{[get_pct()]} that gets rf data from the PCT.
26 | }
27 | \examples{
28 | \dontrun{
29 | # don't test to reduce build times
30 | rf = get_pct_routes_fast("isle-of-wight")
31 | plot(rf)
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/man/get_pct_routes_quiet.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/get_pct.R
3 | \name{get_pct_routes_quiet}
4 | \alias{get_pct_routes_quiet}
5 | \title{Get quiet road network results from the PCT}
6 | \usage{
7 | get_pct_routes_quiet(
8 | region = NULL,
9 | purpose = "commute",
10 | geography = "lsoa",
11 | extension = ".geojson"
12 | )
13 | }
14 | \arguments{
15 | \item{region}{The PCT region or local authority to download data from (e.g. \code{west-yorkshire} or \code{Leeds}).
16 | See \code{View(pct_regions_lookup)} for a full list of possible region names.}
17 |
18 | \item{purpose}{Trip purpose (typically \code{school} or \code{commute})}
19 |
20 | \item{geography}{Geographic resolution of outputs, \code{msoa} or \code{lsoa} (the default)}
21 |
22 | \item{extension}{The type of file to download (only \code{.geojson} supported at present)}
23 | }
24 | \description{
25 | Wrapper around \verb{[get_pct()]} that gets rq data from the PCT.
26 | }
27 | \examples{
28 | \dontrun{
29 | # don't test to reduce build times
30 | rq = get_pct_routes_quiet("isle-of-wight")
31 | plot(rq)
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/man/get_pct_zones.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/get_pct.R
3 | \name{get_pct_zones}
4 | \alias{get_pct_zones}
5 | \title{Get zone results from the PCT}
6 | \usage{
7 | get_pct_zones(
8 | region = NULL,
9 | purpose = "commute",
10 | geography = "lsoa",
11 | extension = ".geojson"
12 | )
13 | }
14 | \arguments{
15 | \item{region}{The PCT region or local authority to download data from (e.g. \code{west-yorkshire} or \code{Leeds}).
16 | See \code{View(pct_regions_lookup)} for a full list of possible region names.}
17 |
18 | \item{purpose}{Trip purpose (typically \code{school} or \code{commute})}
19 |
20 | \item{geography}{Geographic resolution of outputs, \code{msoa} or \code{lsoa} (the default)}
21 |
22 | \item{extension}{The type of file to download (only \code{.geojson} supported at present)}
23 | }
24 | \description{
25 | Wrapper around \verb{[get_pct()]} that gets zone data from the PCT.
26 | }
27 | \examples{
28 | \dontrun{
29 | # don't test to reduce build times
30 | z = get_pct_zones("isle-of-wight")
31 | plot(z)
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/man/leeds_uber_sample.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \name{leeds_uber_sample}
5 | \alias{leeds_uber_sample}
6 | \title{Top 15 min mean journy times within Leeds from Uber}
7 | \description{
8 | Data downloaded 4th March 2019.
9 | According to Uber, the dataset is from:
10 | 1/1/2018 - 1/31/2018 (Every day, Daily Average)
11 | }
12 | \examples{
13 | # see data-raw folder for generation code
14 | leeds_uber_sample
15 | }
16 | \keyword{datasets}
17 |
--------------------------------------------------------------------------------
/man/mode_names.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \name{mode_names}
5 | \alias{mode_names}
6 | \title{Mode names in the Census}
7 | \description{
8 | And conversion into R-friendly versions
9 | }
10 | \examples{
11 | mode_names
12 | }
13 | \keyword{datasets}
14 |
--------------------------------------------------------------------------------
/man/model_pcycle_pct_2020.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/model.R
3 | \name{model_pcycle_pct_2020}
4 | \alias{model_pcycle_pct_2020}
5 | \title{Model cycling levels as a function of explanatory variables}
6 | \usage{
7 | model_pcycle_pct_2020(pcycle, distance, gradient, weights)
8 | }
9 | \arguments{
10 | \item{pcycle}{The proportion of trips by bike, e.g. 0.1, meaning 10\%}
11 |
12 | \item{distance}{Vector distance numeric values of routes in km
13 | (switches to km if more than 100).}
14 |
15 | \item{gradient}{Vector gradient numeric values of routes.}
16 |
17 | \item{weights}{The weights used in the model, typically the total number of people per OD pair}
18 | }
19 | \description{
20 | Model cycling levels as a function of explanatory variables
21 | }
22 | \examples{
23 | # l = get_pct_lines(region = "isle-of-wight")
24 | # l = get_pct_lines(region = "cambridgeshire")
25 | l = wight_lines_pct
26 | pcycle = l$bicycle / l$all
27 | pcycle_dutch = l$dutch_slc / l$all
28 | m1 = model_pcycle_pct_2020(
29 | pcycle,
30 | distance = l$rf_dist_km,
31 | gradient = l$rf_avslope_perc - 0.78,
32 | weights = l$all
33 | )
34 | m2 = model_pcycle_pct_2020(
35 | pcycle_dutch, distance = l$rf_dist_km,
36 | gradient = l$rf_avslope_perc - 0.78,
37 | weights = l$all
38 | )
39 | m3 = model_pcycle_pct_2020(
40 | pcycle_dutch, distance = l$rf_dist_km,
41 | gradient = l$rf_avslope_perc - 0.78,
42 | weights = rep(1, nrow(l))
43 | )
44 | m1
45 | plot(l$rf_dist_km, pcycle, cex = l$all / 100, ylim = c(0, 0.5))
46 | points(l$rf_dist_km, m1$fitted.values, col = "red")
47 | points(l$rf_dist_km, m2$fitted.values, col = "blue")
48 | points(l$rf_dist_km, pcycle_dutch, col = "green")
49 | cor(l$dutch_slc, m2$fitted.values * l$all)^2 # 95\% captured
50 | # identical means:
51 | mean(l$dutch_slc)
52 | mean(m2$fitted.values * l$all)
53 | pct_coefficients_2020 = c(
54 | alpha = -4.018 + 2.550,
55 | d1 = -0.6369 -0.08036,
56 | d2 = 1.988,
57 | d3 = 0.008775,
58 | h1 = -0.2555,
59 | i1 = 0.02006,
60 | i2 = -0.1234
61 | )
62 | pct_coefficients_2020
63 | m2$coef
64 | plot(pct_coefficients_2020, m2$coeff)
65 | cor(pct_coefficients_2020, m2$coeff)^2
66 | cor(pct_coefficients_2020, m3$coeff)^2 # explains 95\%+ variability in params
67 | }
68 |
--------------------------------------------------------------------------------
/man/od_leeds.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \name{od_leeds}
5 | \alias{od_leeds}
6 | \title{Example OD data for Leeds}
7 | \description{
8 | \code{od_leeds} contains the 100 most travelled work desire lines in Leeds,
9 | according to the 2011 Census.
10 | }
11 | \examples{
12 | # see data-raw folder for generation code
13 | od_leeds
14 | }
15 | \keyword{datasets}
16 |
--------------------------------------------------------------------------------
/man/pct_regions.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \name{pct_regions}
5 | \alias{pct_regions}
6 | \title{PCT regions from www.pct.bike}
7 | \description{
8 | See data-raw folder for generation code
9 | }
10 | \examples{
11 | pct_regions
12 | }
13 | \keyword{datasets}
14 |
--------------------------------------------------------------------------------
/man/pct_regions_lookup.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \name{pct_regions_lookup}
5 | \alias{pct_regions_lookup}
6 | \title{Lookup table matching PCT regions to local authorities}
7 | \description{
8 | For matching pct_regions object with local authority names in England and Wales.
9 | }
10 | \examples{
11 |
12 | names(pct_regions_lookup)
13 | head(pct_regions_lookup)
14 | }
15 | \keyword{datasets}
16 |
--------------------------------------------------------------------------------
/man/rnet_leeds.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \name{rnet_leeds}
5 | \alias{rnet_leeds}
6 | \title{Route network for Leeds}
7 | \description{
8 | Route network for Leeds
9 | }
10 | \examples{
11 | # see data-raw folder for generation code
12 | rnet_leeds
13 | }
14 | \keyword{datasets}
15 |
--------------------------------------------------------------------------------
/man/routes_fast_leeds.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \name{routes_fast_leeds}
5 | \alias{routes_fast_leeds}
6 | \title{Fastest cycle routes for the desire_lines_leeds}
7 | \description{
8 | Fastest cycle routes for the desire_lines_leeds
9 | }
10 | \examples{
11 | # see data-raw folder for generation code
12 | routes_fast_leeds
13 | }
14 | \keyword{datasets}
15 |
--------------------------------------------------------------------------------
/man/santiago_lines.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \name{santiago_lines}
5 | \alias{santiago_lines}
6 | \title{Desire lines in central Santiago}
7 | \description{
8 | See https://github.com/pedalea/pctSantiago folder for generation code
9 | }
10 | \examples{
11 | # u = "https://github.com/pedalea/pctSantiago/releases/download/0.0.1/od_agg_zone_sub.Rds"
12 | # download.file(u, destfile = "od_agg_zone_sub.Rds")
13 | # desire_lines = readRDS("od_agg_zone_sub.Rds")
14 | santiago_zones
15 | }
16 | \keyword{datasets}
17 |
--------------------------------------------------------------------------------
/man/santiago_od.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \name{santiago_od}
5 | \alias{santiago_od}
6 | \title{OD data in central Santiago}
7 | \description{
8 | See https://github.com/pedalea/pctSantiago folder for generation code
9 | }
10 | \examples{
11 | # u = "https://github.com/pedalea/pctSantiago/releases/download/0.0.1/santiago_od.Rds"
12 | # download.file(u, destfile = "santiago_od.Rds", mode = "wb")
13 | # santiago_od = readRDS("santiago_od.Rds")
14 | santiago_od
15 | }
16 | \keyword{datasets}
17 |
--------------------------------------------------------------------------------
/man/santiago_routes_cs.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \name{santiago_routes_cs}
5 | \alias{santiago_routes_cs}
6 | \title{200 cycle routes in central Santiago, Chile}
7 | \description{
8 | This data was obtained using code shown in the
9 | International application of the PCT methods
10 | \href{https://itsleeds.github.io/pct/articles/pct-international.html}{vignette}.
11 | }
12 | \examples{
13 | library(sf)
14 | names(santiago_routes_cs)
15 | head(santiago_routes_cs)
16 | plot(santiago_routes_cs)
17 | }
18 | \keyword{datasets}
19 |
--------------------------------------------------------------------------------
/man/santiago_zones.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \name{santiago_zones}
5 | \alias{santiago_zones}
6 | \title{Zones in central Santiago}
7 | \description{
8 | See https://github.com/pedalea/pctSantiago folder for generation code
9 | }
10 | \examples{
11 | # u = "https://github.com/pedalea/pctSantiago/releases/download/0.0.1/z_centre.Rds"
12 | # download.file(u, destfile = "z_centre.Rds", mode = "wb")
13 | # santiago_zones = readRDS("z_centre.Rds")
14 | santiago_zones
15 | }
16 | \keyword{datasets}
17 |
--------------------------------------------------------------------------------
/man/uptake_pct_godutch.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/uptake.R
3 | \name{uptake_pct_godutch}
4 | \alias{uptake_pct_godutch}
5 | \title{Calculate cycling uptake for UK 'Go Dutch' scenario}
6 | \usage{
7 | uptake_pct_godutch(
8 | distance,
9 | gradient,
10 | alpha = -3.959 + 2.523,
11 | d1 = -0.5963 - 0.07626,
12 | d2 = 1.866,
13 | d3 = 0.00805,
14 | h1 = -0.271,
15 | i1 = 0.009394,
16 | i2 = -0.05135,
17 | verbose = FALSE
18 | )
19 | }
20 | \arguments{
21 | \item{distance}{Vector distance numeric values of routes in km
22 | (switches to km if more than 100).}
23 |
24 | \item{gradient}{Vector gradient numeric values of routes.}
25 |
26 | \item{alpha}{The intercept}
27 |
28 | \item{d1}{Distance term 1}
29 |
30 | \item{d2}{Distance term 2}
31 |
32 | \item{d3}{Distance term 3}
33 |
34 | \item{h1}{Hilliness term 1}
35 |
36 | \item{i1}{Distance-hilliness interaction term 1}
37 |
38 | \item{i2}{Distance-hilliness interaction term 2}
39 |
40 | \item{verbose}{Print messages? \code{FALSE} by default.}
41 | }
42 | \description{
43 | This function implements the uptake model described in the original
44 | Propensity to Cycle Tool paper (Lovelace et al. 2017):
45 | https://doi.org/10.5198/jtlu.2016.862
46 | }
47 | \details{
48 | See \code{\link[=uptake_pct_govtarget]{uptake_pct_govtarget()}}.
49 | }
50 | \examples{
51 | # https://www.jtlu.org/index.php/jtlu/article/download/862/1381/4359
52 | # Equation 1B:
53 | distance = 15
54 | gradient = 2
55 | logit = -3.959 + 2.523 +
56 | ((-0.5963 - 0.07626) * distance) +
57 | (1.866 * sqrt(distance)) +
58 | (0.008050 * distance^2) +
59 | (-0.2710 * gradient) +
60 | (0.009394 * distance * gradient) +
61 | (-0.05135 * sqrt(distance) * gradient)
62 | logit
63 | # Result: -3.144098
64 |
65 | pcycle = exp(logit) / (1 + exp(logit))
66 | # Result: 0.04132445
67 | boot::inv.logit(logit)
68 | uptake_pct_godutch(distance, gradient,
69 | alpha = -3.959 + 2.523, d1 = -0.5963 - 0.07626,
70 | d2 = 1.866, d3 = 0.008050, h1 = -0.2710, i1 = 0.009394, i2 = -0.05135
71 | )
72 | # these are the default values
73 | uptake_pct_godutch(distance, gradient)
74 | l = routes_fast_leeds
75 | pcycle_scenario = uptake_pct_godutch(l$length, l$av_incline)
76 | plot(l$length, pcycle_scenario)
77 | }
78 |
--------------------------------------------------------------------------------
/man/uptake_pct_govtarget.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/uptake.R
3 | \name{uptake_pct_govtarget}
4 | \alias{uptake_pct_govtarget}
5 | \alias{uptake_pct_govtarget_2020}
6 | \alias{uptake_pct_godutch_2020}
7 | \alias{uptake_pct_ebike_2020}
8 | \alias{uptake_pct_govtarget_school2}
9 | \alias{uptake_pct_godutch_school2}
10 | \title{Calculate cycling uptake for UK 'Government Target' scenario}
11 | \usage{
12 | uptake_pct_govtarget(
13 | distance,
14 | gradient,
15 | alpha = -3.959,
16 | d1 = -0.5963,
17 | d2 = 1.866,
18 | d3 = 0.00805,
19 | h1 = -0.271,
20 | i1 = 0.009394,
21 | i2 = -0.05135,
22 | verbose = FALSE
23 | )
24 |
25 | uptake_pct_govtarget_2020(
26 | distance,
27 | gradient,
28 | alpha = -4.018,
29 | d1 = -0.6369,
30 | d2 = 1.988,
31 | d3 = 0.008775,
32 | h1 = -0.2555,
33 | h2 = -0.78,
34 | i1 = 0.02006,
35 | i2 = -0.1234,
36 | verbose = FALSE
37 | )
38 |
39 | uptake_pct_godutch_2020(
40 | distance,
41 | gradient,
42 | alpha = -4.018 + 2.55,
43 | d1 = -0.6369 - 0.08036,
44 | d2 = 1.988,
45 | d3 = 0.008775,
46 | h1 = -0.2555,
47 | h2 = -0.78,
48 | i1 = 0.02006,
49 | i2 = -0.1234,
50 | verbose = FALSE
51 | )
52 |
53 | uptake_pct_ebike_2020(
54 | distance,
55 | gradient,
56 | alpha = -4.018 + 2.55,
57 | d1 = -0.6369 - 0.08036 + 0.05509,
58 | d2 = 1.988,
59 | d3 = 0.008775 - 0.000295,
60 | h1 = -0.2555 + 0.1812,
61 | h2 = -0.78,
62 | i1 = 0.02006,
63 | i2 = -0.1234,
64 | verbose = FALSE
65 | )
66 |
67 | uptake_pct_govtarget_school2(
68 | distance,
69 | gradient,
70 | alpha = -7.178,
71 | d1 = -1.87,
72 | d2 = 5.961,
73 | h1 = -0.529,
74 | h2 = -0.63,
75 | verbose = FALSE
76 | )
77 |
78 | uptake_pct_godutch_school2(
79 | distance,
80 | gradient,
81 | alpha = -7.178 + 3.574,
82 | d1 = -1.87 + 0.3438,
83 | d2 = 5.961,
84 | h1 = -0.529,
85 | h2 = -0.63,
86 | verbose = FALSE
87 | )
88 | }
89 | \arguments{
90 | \item{distance}{Vector distance numeric values of routes in km
91 | (switches to km if more than 100).}
92 |
93 | \item{gradient}{Vector gradient numeric values of routes.}
94 |
95 | \item{alpha}{The intercept}
96 |
97 | \item{d1}{Distance term 1}
98 |
99 | \item{d2}{Distance term 2}
100 |
101 | \item{d3}{Distance term 3}
102 |
103 | \item{h1}{Hilliness term 1}
104 |
105 | \item{i1}{Distance-hilliness interaction term 1}
106 |
107 | \item{i2}{Distance-hilliness interaction term 2}
108 |
109 | \item{verbose}{Print messages? \code{FALSE} by default.}
110 |
111 | \item{h2}{Hilliness term 2}
112 | }
113 | \description{
114 | Uptake model that takes distance and hilliness and returns
115 | a percentage of trips that could be made by cycling along a desire line
116 | under scenarios of change. Source: appendix of pct paper, hosted at:
117 | \href{https://www.jtlu.org/index.php/jtlu/article/download/862/1381/4359}{www.jtlu.org}
118 | which states that: "To estimate cycling potential,the Propensity to Cycle Tool (PCT) was
119 | designed to use the best available geographically disaggregated
120 | data sources on travel patterns."
121 | }
122 | \details{
123 | The functional form of the cycling uptake model used in the PCT is as follows:
124 | (Source: \href{https://npct.github.io/pct-shiny/regions_www/www/static/03a_manual/pct-bike-eng-user-manual-c1.pdf}{npct.github.io})
125 |
126 | \if{html}{\out{}}\preformatted{logit (pcycle) = -3.959 + # alpha
127 | (-0.5963 * distance) + # d1
128 | (1.866 * distancesqrt) + # d2
129 | (0.008050 * distancesq) + # d3
130 | (-0.2710 * gradient) + # h1
131 | (0.009394 * distance * gradient) + # i1
132 | (-0.05135 * distancesqrt *gradient) # i2
133 |
134 | pcycle = exp ([logit (pcycle)]) / (1 + (exp([logit(pcycle)])
135 | }\if{html}{\out{
}}
136 |
137 | \code{uptake_pct_govtarget_2020()} and
138 | \code{uptake_pct_godutch_2020()}
139 | approximate the uptake models used in the updated 2020 release of
140 | the PCT results.
141 |
142 | If the \code{distance} parameter is greater than 100, it is assumed that it is in m.
143 | If for some reason you want to model cycling uptake associated with trips with
144 | distances of less than 100 m, convert the distances to km first.
145 | }
146 | \examples{
147 | distance = 15
148 | gradient = 2
149 | logit_pcycle = -3.959 + # alpha
150 | (-0.5963 * distance) + # d1
151 | (1.866 * sqrt(distance)) + # d2
152 | (0.008050 * distance^2) + # d3
153 | (-0.2710 * gradient) + # h1
154 | (0.009394 * distance * gradient) + # i1
155 | (-0.05135 * sqrt(distance) * gradient) # i2
156 | boot::inv.logit(logit_pcycle)
157 | uptake_pct_govtarget(15, 2)
158 | l = routes_fast_leeds
159 | pcycle_scenario = uptake_pct_govtarget(l$length, l$av_incline)
160 | pcycle_scenario_2020 = uptake_pct_govtarget_2020(l$length, l$av_incline)
161 | plot(l$length, pcycle_scenario, ylim = c(0, 0.2))
162 | points(l$length, pcycle_scenario_2020, col = "blue")
163 |
164 | # compare with published PCT data:
165 | \dontrun{
166 | l_pct_2020 = get_pct_lines(region = "isle-of-wight")
167 | # test for another region:
168 | # l_pct_2020 = get_pct_lines(region = "west-yorkshire")
169 | l_pct_2020$rf_avslope_perc[1:5]
170 | l_pct_2020$rf_dist_km[1:5]
171 | govtarget_slc = uptake_pct_govtarget(
172 | distance = l_pct_2020$rf_dist_km,
173 | gradient = l_pct_2020$rf_avslope_perc
174 | ) * l_pct_2020$all + l_pct_2020$bicycle
175 | govtarget_slc_2020 = uptake_pct_govtarget_2020(
176 | distance = l_pct_2020$rf_dist_km,
177 | gradient = l_pct_2020$rf_avslope_perc
178 | ) * l_pct_2020$all + l_pct_2020$bicycle
179 | mean(l_pct_2020$govtarget_slc)
180 | mean(govtarget_slc)
181 | mean(govtarget_slc_2020)
182 | godutch_slc = uptake_pct_godutch(
183 | distance = l_pct_2020$rf_dist_km,
184 | gradient = l_pct_2020$rf_avslope_perc
185 | ) * l_pct_2020$all + l_pct_2020$bicycle
186 | godutch_slc_2020 = uptake_pct_godutch_2020(
187 | distance = l_pct_2020$rf_dist_km,
188 | gradient = l_pct_2020$rf_avslope_perc
189 | ) * l_pct_2020$all + l_pct_2020$bicycle
190 | mean(l_pct_2020$dutch_slc)
191 | mean(godutch_slc)
192 | mean(godutch_slc_2020)
193 | }
194 | # Take an origin destination (OD) pair between an LSOA centroid and a
195 | # secondary school. In this OD pair, 30 secondary school children travel, of
196 | # whom 3 currently cycle. The fastest route distance is 3.51 km and the
197 | # gradient is 1.11\%. The
198 | # gradient as centred on Dutch hilliness levels is 1.11 – 0.63 = 0.48\%.
199 | # The observed number of cyclists is 2. ... Modelled baseline= 30 * .0558 = 1.8.
200 | uptake_pct_govtarget_school2(3.51, 1.11)
201 | # pcycle = exp ([logit (pcycle)])/(1 + (exp([logit(pcycle)]))).
202 | # pcycle = exp(1.953)/(1 + exp(1.953)) = .8758, or 87.58\%.
203 | uptake_pct_godutch_school2(3.51, 1.11)
204 | }
205 |
--------------------------------------------------------------------------------
/man/wight_lines_30.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \name{wight_lines_30}
5 | \alias{wight_lines_30}
6 | \alias{wight_lines_pct}
7 | \title{Desire lines from the PCT for the Isle of Wight}
8 | \description{
9 | This data was obtained using code shown in the introductory
10 | \href{https://itsleeds.github.io/pct/articles/pct.html}{pct package vignette}.
11 | }
12 | \examples{
13 | names(wight_lines_30)
14 | plot(wight_lines_30)
15 | }
16 | \keyword{datasets}
17 |
--------------------------------------------------------------------------------
/man/wight_od.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \name{wight_od}
5 | \alias{wight_od}
6 | \title{Official origin-destination data for the Isle of Wight}
7 | \description{
8 | This data was obtained using code shown in the introductory
9 | \href{https://itsleeds.github.io/pct/articles/pct.html}{pct package vignette}.
10 | }
11 | \examples{
12 | names(wight_od)
13 | head(wight_od)
14 | }
15 | \keyword{datasets}
16 |
--------------------------------------------------------------------------------
/man/wight_routes_30.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \name{wight_routes_30}
5 | \alias{wight_routes_30}
6 | \alias{wight_rnet}
7 | \alias{wight_routes_30_cs}
8 | \title{Cycle route data for the Isle of Wight}
9 | \description{
10 | This data was obtained using code shown in the introductory
11 | \href{https://itsleeds.github.io/pct/articles/pct.html}{pct package vignette}.
12 | }
13 | \examples{
14 | library(sf)
15 | names(wight_routes_30)
16 | head(wight_routes_30)
17 | plot(wight_routes_30)
18 | }
19 | \keyword{datasets}
20 |
--------------------------------------------------------------------------------
/man/wight_zones.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \name{wight_zones}
5 | \alias{wight_zones}
6 | \alias{wight_centroids}
7 | \title{Zones and centroid data from the PCT for the Isle of Wight}
8 | \description{
9 | This data was obtained using code shown in the introductory
10 | \href{https://itsleeds.github.io/pct/articles/pct.html}{pct package vignette}.
11 | }
12 | \examples{
13 | library(sf)
14 | names(wight_lines_30)
15 | plot(wight_lines_30)
16 | }
17 | \keyword{datasets}
18 |
--------------------------------------------------------------------------------
/man/zones_leeds.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \name{zones_leeds}
5 | \alias{zones_leeds}
6 | \title{Zone data for Leeds}
7 | \description{
8 | Zones in Leeds
9 | }
10 | \examples{
11 | # see data-raw folder for generation code
12 | zones_leeds
13 | }
14 | \keyword{datasets}
15 |
--------------------------------------------------------------------------------
/pct-leeds-demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsleeds/pct/8b68960c60c5e05e782f53e3b259c72ef48f49a6/pct-leeds-demo.png
--------------------------------------------------------------------------------
/pct.Rproj:
--------------------------------------------------------------------------------
1 | Version: 1.0
2 |
3 | RestoreWorkspace: Default
4 | SaveWorkspace: Default
5 | AlwaysSaveHistory: Default
6 |
7 | EnableCodeIndexing: Yes
8 | UseSpacesForTab: Yes
9 | NumSpacesForTab: 2
10 | Encoding: UTF-8
11 |
12 | RnwWeave: Sweave
13 | LaTeX: XeLaTeX
14 |
15 | AutoAppendNewline: Yes
16 | StripTrailingWhitespace: Yes
17 |
18 | BuildType: Package
19 | PackageUseDevtools: Yes
20 | PackageInstallArgs: --no-multiarch --with-keep.source
21 |
--------------------------------------------------------------------------------
/vignettes/.gitignore:
--------------------------------------------------------------------------------
1 | *.html
2 | *.R
3 |
--------------------------------------------------------------------------------
/vignettes/cycling-potential-uk.Rmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Cycling potential in UK cities"
3 | output: rmarkdown::html_vignette
4 | vignette: >
5 | %\VignetteIndexEntry{Cycling potential in UK cities}
6 | %\VignetteEngine{knitr::rmarkdown}
7 | %\VignetteEncoding{UTF-8}
8 | ---
9 |
10 | ```{r, include = FALSE}
11 | knitr::opts_chunk$set(
12 | collapse = TRUE,
13 | comment = "#>",
14 | eval = FALSE
15 | )
16 | ```
17 |
18 | Note: this vignette is not evaluated to reduce package build times.
19 | See https://rpubs.com/RobinLovelace/749112 for the results with the code running.
20 |
21 | What modal shift to cycling do you think we could achieve in UK cities in an ideal scenario?
22 | Answers to that question are vital to support high level ambition for active transport and wider sustainability policies in settlements worldwide.
23 | In UK cities such as Leeds (where the motivation for this article originated, via Twitter^[
24 | See `https://twitter.com/PaulChatterton9/status/1190925153322098690` for the original tweet.
25 | ]) there is already a wealth of freely available data on cycling potential, based on the Propensity to Cycle Tool ([PCT](https://www.pct.bike/)) project, of which this package is a part.
26 | This article will briefly explain how to get cycling potential data for any city in England and Wales, based on a case study of Leeds.
27 |
28 | # Getting the region of interest
29 |
30 | The first stage in many projects involving geographic data is to define the region of interest.
31 | In our case we will use the boundary of the Leeds local authority as the basis of analysis.
32 | The PCT is based on 'PCT regions' that we can visualise as follows:
33 |
34 |
35 | ```{r setup, message=FALSE, warning=FALSE}
36 | library(pct)
37 | library(sf)
38 | library(dplyr)
39 | library(tmap)
40 | tm_shape(pct_regions) +
41 | tm_polygons() +
42 | tm_text("region_name", size = 0.6)
43 | ```
44 |
45 | We are interested in Leeds in the `west-yorkshire` area.
46 | Using the `pct` package we can get zone data from the PCT as follows (note: this would work by setting `region_of_interest` to any of the regions shown in the map above:
47 |
48 | ```{r}
49 | region_of_interest = "west-yorkshire"
50 | zones_region = get_pct_zones(region = region_of_interest)
51 | # zones_region = get_pct_zones(region = region_of_interest, geography = "lsoa") # for smaller zones
52 | names(zones_region)
53 | plot(zones_region["bicycle"])
54 | ```
55 |
56 | ```{r, eval=FALSE, echo=FALSE}
57 |
58 | # tm_shape(zones_region) +
59 | # tm_fill("bicycle", palette = "RdYlBu") +
60 | # tm_shape(pct_regions) +
61 | # tm_borders() +
62 | # tm_text("region_name")
63 |
64 | # reproducible example of fail
65 |
66 | remotes::install_github("mtennekes/tmap")
67 | library(tmap)
68 | u = "https://github.com/npct/pct-outputs-regional-notR/raw/master/commute/lsoa/isle-of-wight/z.geojson"
69 | z = sf::st_read(u)
70 | plot(z["bicycle"])
71 | qtm(z)
72 | tm_shape(z) +
73 | tm_fill("bicycle", palette = "RdYlBu")
74 | tmap_mode("view")
75 | qtm(z)
76 |
77 | # another region
78 | tmap_mode("plot")
79 | u = "https://github.com/npct/pct-outputs-regional-notR/raw/master/commute/lsoa/west-yorkshire/z.geojson"
80 | z = sf::st_read(u)
81 | plot(z["bicycle"])
82 | qtm(z)
83 | tm_shape(z) +
84 | tm_fill("bicycle", palette = "RdYlBu")
85 | tmap_mode("view")
86 | qtm(z)
87 | mapview::mapview(z)
88 |
89 | devtools::session_info()
90 | ```
91 |
92 |
93 |
94 | This shows the number of people who say they cycled to work in the 2011 Census.
95 | This may have changed slightly as cycling becomes more popular in some places, but is a good proxy for current cycling levels.
96 | But there are two big problems with this: the map is of West Yorkshire not Leeds, and it's showing current cycling rates, not future potential.
97 |
98 | # Getting cycling potential accross local authorities
99 |
100 | We can find out what local authorities there are in the zones as follows:
101 |
102 | ```{r}
103 | unique(zones_region$lad_name)
104 | ```
105 |
106 | We are interested in the zones in Leeds, which we can get as follows:
107 |
108 | ```{r}
109 | zones = zones_region %>%
110 | filter(lad_name == "Leeds")
111 | tm_shape(zones) +
112 | tm_fill("bicycle", palette = "RdYlBu")
113 | ```
114 |
115 | Great, this represents the current level of cycling across the region of interest.
116 | What about cycling potential? Based on the modelling work in the PCT, we have pre-calculated this for a number of scenarios.
117 | Let's take a look at cycling to work under the Government Target (near market), Go Dutch and Ebikes scenarios for cycling to work:
118 |
119 | ```{r}
120 | scenarios_of_interest = c("govnearmkt_slc", "dutch_slc", "ebike_slc")
121 | tm_shape(zones) +
122 | tm_fill(scenarios_of_interest, palette = "RdYlBu", n = 9, title = "N. cycling") +
123 | tm_facets(nrow = 1, free.scales = FALSE) +
124 | tm_layout(panel.labels = scenarios_of_interest)
125 | ```
126 |
127 | That's great, but it doesn't answer the question of mode share.
128 |
129 | # Cycling mode share
130 |
131 | We can calculate this by dividing the number of people cycling to work by the total:
132 |
133 | ```{r}
134 | zones_mode_share = zones %>%
135 | select(scenarios_of_interest) %>%
136 | mutate_at(scenarios_of_interest, .funs = list(~ ./zones$all * 100))
137 | tm_shape(zones_mode_share) +
138 | tm_fill(scenarios_of_interest, palette = "RdYlBu", title = "% cycling") +
139 | tm_facets(nrow = 1, free.scales = FALSE) +
140 | tm_layout(panel.labels = scenarios_of_interest)
141 | ```
142 |
143 | The summary mode shares can be estimated as follows, with results showing the % cycling currently (according to the 2011 census) and under scenarios of change:
144 |
145 | ```{r}
146 | zones_region %>%
147 | st_drop_geometry() %>%
148 | group_by(lad_name) %>%
149 | select(`2011 census` = bicycle, c(scenarios_of_interest, "all")) %>%
150 | summarise_all(.funs = ~ round(sum(.)/sum(all)* 100)) %>%
151 | select(-all, `Local Authority / % Cycling in scenario:` = lad_name) %>%
152 | knitr::kable()
153 | ```
154 |
155 |
156 |
157 |
158 |
159 | # Cycling potential nationwide
160 |
161 | To generalise the analysis outlined above, we can download national data from the PCT project as follows:
162 |
163 | ```{r national-dl}
164 | zones_national = read_sf("https://github.com/npct/pct-outputs-national/raw/master/commute/msoa/z_all.geojson")
165 | ```
166 |
167 | A summary of cycling potential nationwide can then be calculated as follows:
168 |
169 | ```{r}
170 | national_commute_totals = zones_national %>%
171 | st_drop_geometry() %>%
172 | select(all, census_2011 = bicycle, govtarget_slc, dutch_slc) %>%
173 | summarise_all(.funs = ~sum(.))
174 | national_commute_percentages = national_commute_totals / national_commute_totals$all * 100
175 | ```
176 |
177 | ```{r, echo=FALSE}
178 | knitr::kable(bind_rows(national_commute_totals, national_commute_percentages), digits = 1,
179 | caption = "Total counts and percentages of cycle commuters under different scenarios")
180 | ```
181 |
182 | We can calculate the mode share of cycling under these same scenarios for any area (e.g. the boundary of Greater London) or for a list of named local authorities, as follows:
183 |
184 | ```{r}
185 | r = read.csv(stringsAsFactors = FALSE, text = "area
186 | Greater London
187 | Greater Manchester
188 | Birmingham
189 | Leeds
190 | Glasgow
191 | Liverpool
192 | Newcastle
193 | Bristol
194 | Cardiff
195 | Belfast
196 | Southampton
197 | Sheffield
198 | ")
199 | matching_las = pct_regions_lookup$lad16nm[pct_regions_lookup$lad16nm %in% r$area]
200 | matching_regions = c("london", "greater-manchester")
201 | pct_lookup = pct_regions_lookup %>%
202 | rename(lad_name = lad16nm)
203 | zones_national = inner_join(zones_national, pct_lookup)
204 | zones_national = zones_national %>%
205 | mutate(area = case_when(
206 | region_name == "london" ~ "Greater London",
207 | region_name == "greater-manchester" ~ "Greater Manchester",
208 | lad_name %in% matching_las ~ lad_name,
209 | TRUE ~ "Other"
210 | ))
211 | table(zones_national$area)
212 | zones_aggregated = zones_national %>%
213 | sf::st_drop_geometry() %>%
214 | group_by(area) %>%
215 | summarise(
216 | Commuters = sum(all, na.rm = TRUE),
217 | Bicycle_census = sum(bicycle),
218 | Bicycle_govtarget = sum(govtarget_slc),
219 | Bicycle_godutch = sum(dutch_slc)
220 | )
221 |
222 | # plot(zones_aggregated["Commuters"], border = NA)
223 | zones_aggregated %>%
224 | inner_join(r, .) %>%
225 | knitr::kable(digits = 0)
226 | ```
227 |
228 | Next we can calculate the mode splits as follows:
229 |
230 | ```{r}
231 | zones_aggregated_percents = zones_aggregated %>%
232 | mutate_at(vars(-Commuters, -area), funs(./Commuters * 100))
233 | names(zones_aggregated_percents)[3:5] = paste0(names(zones_aggregated_percents)[3:5], "_percent")
234 | zones_aggregated_percents %>%
235 | inner_join(r, .) %>%
236 | knitr::kable(digits = 1)
237 | ```
238 |
239 | # Considerations
240 |
241 | The results above show that there is huge potential for cycling grow across England and Wales.
242 | Around 16% of commuters in Leeds could cycle to work if we 'Go Dutch' (25% if we Go Dutch and see high uptake of electric bikes) for the single mode journey to work data under consideration.
243 | However, there are some wider considerations that are not captured in the numbers (see the [PCT paper](https://www.jtlu.org/index.php/jtlu/article/view/862) for details and other considerations):
244 |
245 | - The PCT commute layer (don't forget the travel to schools layer!) only considers single stage journeys - if we were to include cycling to the station or bus stop potential it would be greater than 16%, perhaps more like 30% if potential cycle/rail and cycle/bus trips are accounted for.
246 | - Work patterns are changing, and with new digital work practices or a shift towards local economies, more people could work from home or at least near to home.
247 | - The scenarios are snapshots of how cycling levels could change based current trip patterns, not predictions of what will happen. There are many other scenarios that could be developed, including intermediate scenarios between Go Dutch and the Government Target, and more ambitious scenarios, e.g. 'Go Utrecht', where cycling has reached around 60% of trips ([source](https://www.bloomberg.com/news/articles/2019-07-05/how-the-dutch-made-utrecht-a-bicycle-first-city)).
248 |
249 | Other considerations that are often mentioned are hills and people who are unable to cycle.
250 | In fact the PCT accounts for hills and, as the example of Bristol shows, hilly cities can see rapid increases in cycling.
251 | Regarding ability to cycle, it is a more inclusive mode than driving, with 8 to 80 year-olds being able to cycle, and many more people being able to afford a bike than a car (which, thanks to the expense of buying, running and insuring the vehicle, is largely the mode of choice of the wealthy).
252 | The PCT does not account for the fact that some trips to work are also 'caregiving' trips, but with electric cargo bikes and [multi-person cycles](https://en.wikipedia.org/wiki/Cycle_rickshaw) cycling-focused cities can, to a greater extent than car-dominated transport systems, deliver for all.
253 |
254 | ## Challenge
255 |
256 | To anyone interested in cycling in your city: try re-running the reproducible code above for your PCT region and local authority.
257 | Let us know on social media and [GitHub](https://github.com/ITSLeeds/pct/issues) how you get on.
258 | Any comments/contributions to this analysis: [welcome.](https://github.com/ITSLeeds/pct/edit/master/vignettes/cycling-potential-uk.Rmd)
259 |
--------------------------------------------------------------------------------
/vignettes/km-cycled.Rmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Estimating distance cycled per zone in England and Wales regions"
3 | output: rmarkdown::html_vignette
4 | vignette: >
5 | %\VignetteIndexEntry{Estimating distance cycled per zone in England and Wales regions}
6 | %\VignetteEngine{knitr::rmarkdown}
7 | %\VignetteEncoding{UTF-8}
8 | author:
9 | - "Nathanael Sheehan"
10 | ---
11 |
12 | In the context of society, cycling acts as a vessel to mobilise citizens to navigate through spatial geography in a sustainable fashion. In doing so, cycling obtains numerous socio-spatial benefits both at the micro (individual health benefits from active transport) and macro (lower pollution from vehicles) scale. With the ambition of building a sustainable future, the PCT project promotes cycle uptake through providing open tools for policy-makers, transport planners and academics to plan future cycle infrastructure for the built environment.
13 |
14 | Using data from the 2011 census and models built into the PCT package, this article asks the question of "How many km's per LSOA do commuters cycle through each year?". The results of which provide valuable insight into future sustainable transport planning decisions and highlight the versatility of the PCT package through a reproducible method.
15 |
16 | Set `eval=TRUE` to run this code when knitting:
17 |
18 | ```{r}
19 | knitr::opts_chunk$set(eval = FALSE)
20 | ```
21 |
22 |
23 | ## Prerequisites
24 |
25 | The following packages must be installed and loaded to run the code in this vignette.
26 |
27 | ```{r, message=FALSE, warning=FALSE}
28 | # Load packages
29 | library(pct)
30 | library(tmap)
31 | ```
32 |
33 | ## Estimating distance cycled for a region based on 2011 census data
34 |
35 | The PCT package permits an easy method for fetching road network and commuting origin/destination data for any region in England and Wales. This data will be used as the basis for understanding the current context of cycling for a given region (A definition of regions can be found in this earlier article). For this first example, we will apply the pct method to the region of Oxfordshire. To kick things off, we use the ```get_pct_rnet``` to retrieve road network data for the region. This data is then used to calculate the length of the road network cycled using ```base ``` r functions.
36 |
37 | ```{r, message=FALSE, warning=FALSE}
38 | #Get road network for preselected regin
39 | rnet = pct::get_pct_rnet(region = "oxfordshire")
40 | #Calculate road length
41 | rnet$segment_length = as.numeric(sf::st_length(rnet))
42 | #Calculate daily km's cycled
43 | rnet$m_cycled_per_working_day = rnet$segment_length * rnet$bicycle
44 | ```
45 |
46 | Simples! Now we can use the ```get_pct_zones``` function to get LSOA geographies in order to calculate the number of km's cycled per day through each LSOA.
47 |
48 | ```{r, message=FALSE, warning=FALSE}
49 | # Get road network for preselected regin
50 | zones = pct::get_pct_zones(region = "oxfordshire")
51 | summary(sf::st_is_valid(zones))
52 | zones = sf::st_make_valid(zones)
53 | summary(sf::st_is_valid(zones))
54 | cycled_m_per_zone = aggregate(rnet["m_cycled_per_working_day"], zones, FUN = sum)
55 | ```
56 |
57 | While this is great information, it doesn't provide answer the long term question of how many distance are cycled per year. In order to achieve this, we must multiple the number of trips per day by the number of days in a standard working year (200) and divide by a million. Once again, this is achieved using ```base``` r functionality.
58 |
59 | ```{r, message=FALSE, warning=FALSE}
60 | zones$mkm_cycled_for_commuting_per_year_estimated = cycled_m_per_zone$m_cycled_per_working_day *
61 | 2 * 200 / # estimate of trips days per year, morning and afternoon
62 | 1e9
63 | ```
64 |
65 | With this calculated, we can now answer our question and visualize yearly km's cycled using ```tmap```.
66 |
67 | ```{r, message=FALSE, warning=FALSE, fig.align="center", fig.width = 7, fig.height = 6}
68 | tm_shape(zones) +
69 | tm_fill(
70 | col = "mkm_cycled_for_commuting_per_year_estimated",
71 | style = "quantile",
72 | palette = "plasma",
73 | title = "Yearly distance cycled by commuters per day\n(2011 Census Data)",
74 | legend.size.is.portrait = TRUE
75 | ) +
76 | tm_layout(
77 | title = "OXFORDSHIRE",
78 | title.position = c("left", "top"),
79 | bg.color = "honeydew3",
80 | outer.bg.color = "honeydew",
81 | legend.stack = "horizontal",
82 | legend.outside = TRUE,
83 | legend.outside.position = "left",
84 | frame.lwd = 5
85 | )
86 | ```
87 |
88 | Wow, that's a lot of miles cycled! The plot breaks down the number km's cycled by quartiles and thus paints the picture of where cycling is most prominent. In the context of Oxfordshire, the map depecits the region obtainaing a rather high cycle uptake; with its spatial distribution primarily in the centre of the region.
89 |
90 | ## Comparing Regions
91 |
92 | Now say we wanted to compare the results of Oxfordshire, with its regional neighbor Cambridgeshire. This can be achieved by wrapping the previous method into a function.
93 |
94 | ```{r, message=FALSE, warning=FALSE}
95 | pct_zones_rnet_current = function(region_name) {
96 | # Get road network for preselected regin
97 | rnet = pct::get_pct_rnet(region = region_name)
98 | # Calculate road length
99 | rnet$segment_length = as.numeric(sf::st_length(rnet))
100 | # Calculate daily km cycled
101 | rnet$m_cycled_per_working_day = rnet$segment_length * rnet$bicycle
102 | # Convert to centroids to avoid double counting flows that cross zones
103 | rnet_centroids = sf::st_centroid(rnet)
104 | # Get LSOA spatial data
105 | zones = sf::st_make_valid(pct::get_pct_zones(region = region_name))
106 | # Calculate cyced miles per zone
107 | cycled_m_per_zone = aggregate(rnet_centroids["m_cycled_per_working_day"], zones, FUN = sum)
108 | # Calculate miles cycled per year from commuting
109 | zones$mkm_cycled_for_commuting_per_year_estimated = cycled_m_per_zone$m_cycled_per_working_day *
110 | 2 * 200 / # estimate of trips days per year, morning and afternoon
111 | 1e9
112 | # Plot results
113 | tmap_mode("plot")
114 | tm_shape(zones) +
115 | tm_fill(
116 | col = "mkm_cycled_for_commuting_per_year_estimated",
117 | style = "quantile",
118 | palette = "plasma",
119 | title = "Million km's cycled by commuters per year\n(2011 Census Data)",
120 | legend.size.is.portrait = TRUE
121 | ) +
122 | tm_layout(
123 | title = toupper(region_name),
124 | title.position = c("left", "top"),
125 | bg.color = "honeydew3",
126 | outer.bg.color = "honeydew",
127 | legend.stack = "horizontal",
128 | legend.outside = TRUE,
129 | legend.outside.position = "bottom",
130 | frame.lwd = 5
131 | )
132 |
133 | }
134 | ```
135 |
136 | With our function built, we can now easily compare regional differences.
137 |
138 | ```{r, message=FALSE, warning=FALSE, fig.align="center", fig.width = 7, fig.height = 6}
139 | oxfordshire_results = pct_zones_rnet_current(region_name = "oxfordshire")
140 | cambrideshire_results = pct_zones_rnet_current(region_name = "cambridgeshire")
141 | tmap_arrange(oxfordshire_results, cambrideshire_results, ncol = 2)
142 | ```
143 |
144 | In comparison to Oxfordshire, Cambridgeshire spatial distribution of km's cycled exhibit a high number of cycling not only in the centre of the region. While Oxfordshire obtains a zone with a higher number of km's cycled through it, in general Cambridgeshire displays a higher number in its quartile range. Interesting!
145 |
146 | Now lets say we wanted to compare two cities. Lets take London and Greater Manchester.
147 |
148 | ```{r, message=FALSE, warning=FALSE, fig.align="center", fig.width = 7, fig.height = 6}
149 | london_results = pct_zones_rnet_current(region_name = "london")
150 | gm_results = pct_zones_rnet_current(region_name = "greater-manchester")
151 | #tmap_mode("view")
152 | tmap_arrange(london_results, gm_results, ncol = 2)
153 | ```
154 |
155 | Jheeze! The maps provides insight at a highly granular level. Both Greater Manchester and London have similar quartile ranges and are fairly monocentric, however, LSOA's in London such as ```E01032739``` obtain billions in km's cycled per year; likely due to working population differences. Nonetheless, outer LSOA's in both Greater Manchester and London also feature in the highest quartile, representing that cycle uptake is not dominant solely in the centre of the regions.
156 |
157 | ## Using PCT models to visualize potential cycle uptake
158 |
159 | While the results based on the 2011 census provide interesting and valuable results, a lot has changed since 2011 and other scenarios should be explored. The PCT package features numerous models (e.g. ```govtarget_slc```,```gendereq_slc``` and ```ebike_slc```). In this example, lets examine London and Manchester again, but this time, lets use the PCT E-bike model scenario. The PCT E-Bike model assumes commuters will use e-Bikes for longer or hillier trips (based on data from Dutch and Swiss travel surveys). In order to model this, we will build a function similar to what we used for the census data, but change the daily miles cycled to use the ```ebike_slc``` column.
160 |
161 | ```{r, message=FALSE, warning=FALSE}
162 | pct_zones_rnet_ebikes <- function(region_name) {
163 | # Get road network for pre-selected region
164 | rnet = pct::get_pct_rnet(region = region_name)
165 | # Calculate road length
166 | rnet$segment_length = as.numeric(sf::st_length(rnet))
167 | # Calculate daily miles cycled
168 | rnet$m_cycled_per_working_day = rnet$segment_length * rnet$ebike_slc
169 | # Convert to centroids to avoid double counting flows that cross zones
170 | rnet_centroids = sf::st_centroid(rnet)
171 | # Get LSOA spatial data
172 | zones = sf::st_make_valid(pct::get_pct_zones(region = region_name))
173 | # Calculate cycled miles per zone
174 | cycled_m_per_zone = aggregate(rnet_centroids["m_cycled_per_working_day"], zones, FUN = sum)
175 | # Calculate km cycled per year from commuting
176 | zones$mkm_cycled_for_commuting_per_year_estimated = cycled_m_per_zone$m_cycled_per_working_day *
177 | 2 * 200 / # estimate of trips days per year, morning and afternoon
178 | 1e9
179 | #Plot results
180 | tmap_mode("plot")
181 | tm_shape(zones) +
182 | tm_fill(
183 | col = "mkm_cycled_for_commuting_per_year_estimated",
184 | style = "quantile",
185 | palette = "plasma",
186 | title = "Million km's cycled by commuters per year\n(E-Bike model)",
187 | legend.size.is.portrait = TRUE
188 | ) +
189 | tm_layout(
190 | title = toupper(region_name),
191 | title.position = c("left", "top"),
192 | bg.color = "honeydew3",
193 | outer.bg.color = "honeydew",
194 | legend.stack = "horizontal",
195 | legend.outside = TRUE,
196 | legend.outside.position = "bottom",
197 | frame.lwd = 5
198 | )
199 | }
200 | ```
201 |
202 | With our E-Bikes function built, we can map the results to visualise the effect an E-bike scenario may have on these two cities.
203 |
204 | ```{r, message=FALSE, warning=FALSE, fig.align="center", fig.width = 7, fig.height = 6}
205 | london_results_ebikes = pct_zones_rnet_ebikes(region_name = "london")
206 | gm_results_ebikes = pct_zones_rnet_ebikes(region_name = "greater-manchester")
207 | #tmap_mode("view")
208 | tmap_arrange(london_results_ebikes, gm_results_ebikes, ncol = 2)
209 | ```
210 |
211 | Wow! The maps show how an E-Bike scenario could increase cycle uptake by ~500%. As this model illustrates, an E-Bike scenario would mean more LSOA's would be in the highest quartile of distance cycled. This would mean safer roads, cleaner air and a more sustainable future.
212 |
213 | ## Conclusions and next steps
214 |
215 | As demonstrated, the PCT packages provides easy methods to visualize cycle potential. This article has briefly shown how you can use the PCT package models to understand what future cycle uptake could look like and how to calculate the number of km's cycled per year at a granular level. If this article is of use/interest, why not try for your local region showing the potential based on different models. You can also try the following resources (in R and online):
216 |
217 | * Have a play with the PCT web application
218 | * For more of a deep dive into the methods, see the pct_training vignette
219 | * See the pct-international to see how to apply the methods internationally
220 |
221 | We’re interested to know how you’ve used the methods/data so please get in touch on social media and GitHub letting us know how get on. Any comments/contributions to this analysis: welcome.
222 |
--------------------------------------------------------------------------------
/vignettes/nature.csl:
--------------------------------------------------------------------------------
1 |
2 |
126 |
--------------------------------------------------------------------------------
/vignettes/pct-international.Rmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "International application of the PCT methods"
3 | author: "Robin Lovelace, Layik Hama"
4 | date: "`r Sys.Date()`"
5 | output: rmarkdown::html_vignette
6 | vignette: >
7 | %\VignetteIndexEntry{International application of the PCT}
8 | %\VignetteEngine{knitr::rmarkdown}
9 | %\VignetteEncoding{UTF-8}
10 | ---
11 |
12 | ```{r setup, include = FALSE}
13 | knitr::opts_chunk$set(
14 | collapse = TRUE,
15 | comment = "#>"
16 | )
17 | ```
18 |
19 | ## Introduction
20 |
21 | The package README shows how the PCT can be used to get and reproduce some of the datasets from the PCT package, based on an example in the city of Leeds.
22 | This vignette shows how the package can be used to create estimates of cycling potential in other cities.
23 |
24 | Set `eval=TRUE` to run this code when knitting:
25 |
26 | ```{r}
27 | knitr::opts_chunk$set(eval = FALSE)
28 | ```
29 |
30 | Let's start by loading the package:
31 |
32 | ```{r libraries, message=FALSE}
33 | # devtools::install_github("ATFutures/geoplumber")
34 | # require("geojsonsf")
35 | library(pct)
36 | ```
37 |
38 | ## Input data
39 |
40 | The input data for this vignetted was created using code in the [pctSantiago](https://github.com/pedalea/pctSantiago) project.
41 | It looks like this, in terms of the flow data:
42 |
43 | ```{r}
44 | head(santiago_od)
45 | ```
46 |
47 | In terms of the zone data, they look like this:
48 |
49 | ```{r}
50 | sf:::print.sf(santiago_zones)
51 | plot(santiago_zones)
52 | ```
53 |
54 | Note that we have cycling estimates for each desire line.
55 | If this data is not known, current cycling levels can be approximated for all desire lines as the city-wide average, e.g. around 5% for Santiago.
56 |
57 | ## Creating desire lines
58 |
59 | The origin-destination data can be converted to geographic desire lines using the `stplanr` function `od2line` as follows:
60 |
61 | ```{r, warning=FALSE}
62 | desire_lines = stplanr::od2line(flow = santiago_od, zones = santiago_zones)
63 | ```
64 |
65 | The resulting lines can then be plotted on top of zone data as follows:
66 |
67 | ```{r, out.width="100%"}
68 | plot(santiago_zones$geometry)
69 | plot(santiago_lines["pcycle"], lwd = santiago_lines$n / 3, add = TRUE)
70 | # gj = geojsonsf::sf_geojson(santiago_lines)
71 | # path = file.path(tempdir(), "dl.geojson")
72 | # write(gj, path)
73 | # html_map = geoplumber::gp_map(path, browse_map = FALSE)
74 | # htmltools::includeHTML(html_map)
75 | ```
76 |
77 | The previous map suggests that the data is reliable: we have created a good approximation of the travel pattern in central Santiago.
78 |
79 | ## Estimating cycling uptake
80 |
81 | To estimate cycling potential, we need estimates of distance and hilliness.
82 | The area under investigation is relatively flat so we can make the simplifying assumption that hilliness is 0% for all lines (normally we would get this information from a routing service):
83 |
84 | ```{r}
85 | desire_lines$hilliness = 0
86 | ```
87 |
88 | And what about the distance?
89 | We can calculated it as follows (note we converted this into a numeric object to prevent issues associated with the `units` package):
90 |
91 | ```{r}
92 | desire_lines$distance = as.numeric(sf::st_length(desire_lines))
93 | ```
94 |
95 | Now we have (very) crude estimates of distance and hilliness, we can estimate the cycling potential as follows:
96 |
97 | ```{r}
98 | desire_lines$godutch_pcycle = uptake_pct_godutch(distance = desire_lines$distance, gradient = 0)
99 | ```
100 |
101 | Let's take a look at the results, compared with the current levels of cycling, and compared with distance:
102 |
103 | ```{r}
104 | cor(x = desire_lines$pcycle, y = desire_lines$godutch_pcycle)
105 | plot(x = desire_lines$pcycle, y = desire_lines$godutch_pcycle)
106 | plot(x = desire_lines$distance, y = desire_lines$godutch_pcycle, ylim = c(0, 1))
107 | ```
108 |
109 | As expected, there is a positive (albeit small) positive correlation between current and potential levels of cycling.
110 | The result shows clearly that distance decay kicks in just after 2km, but still at 8 km there is a 25% mode share, suggesting a major switch to cycling.
111 |
112 | We can put the results on a map as follows:
113 |
114 | ```{r, out.width="50%", fig.show='hold'}
115 | library(leaflet)
116 | leaflet(width = "100%") %>%
117 | addTiles() %>%
118 | addPolylines(data = desire_lines, weight = desire_lines$pcycle * 5)
119 | leaflet(width = "100%") %>%
120 | addTiles() %>%
121 | addPolylines(data = desire_lines, weight = desire_lines$godutch_pcycle * 5)
122 | ```
123 |
124 | The results show that there is substantial potential for increasing the levels of cycling in central Santiago, based on origin-destination data alone.
125 | However, to inform policy, more detailed estimates of cycling potential are needed, with results that go down to the level of individual streets.
126 | This involves routing.
127 |
128 | ## Routing
129 |
130 | There are many ways to do calculate a path on the street network.
131 | The main options are local routing, where the calculation is done based on data stored locally (on your computer) and routing services, where the data is done remotely ('in the cloud').
132 | Let's use a remote routing service to convert the straight lines generated in the previous section into routes that could realistically be taken by people cycling (the next line does not run by default because it requires an API key saved as an environment variable, see the [documentation of `route_cyclestreets()` for details](https://docs.ropensci.org/stplanr/reference/index.html#section-routing) for details).
133 |
134 | ```{r, eval=FALSE}
135 | santiago_routes_cs = stplanr::line2route(desire_lines)
136 | # > 10 % out of 200 distances calculated
137 | # > 20 % out of 200 distances calculated
138 | # > 30 % out of 200 distances calculated
139 | # > 40 % out of 200 distances calculated
140 | # > 50 % out of 200 distances calculated
141 | # > 60 % out of 200 distances calculated
142 | # > 70 % out of 200 distances calculated
143 | # > 80 % out of 200 distances calculated
144 | # > 90 % out of 200 distances calculated
145 | # > 100 % out of 200 distances calculated
146 | # > Warning message:
147 | # > In value[[3L]](cond) : Fail for line number 32
148 | ```
149 |
150 | Note that one of the routes failed.
151 | We can look at this route as follows, to try to understand what happened:
152 |
153 | ```{r}
154 | leaflet() %>%
155 | addTiles() %>%
156 | addPolylines(data = santiago_routes_cs[32, ])
157 | ```
158 |
159 | The result shows that one end of the route connects to the Sendero Ciclistas, which the routing service may be unable to reach.
160 | At this stage there are 2 main options: 1) to omit the data point from the analysis, acknowledging that the data is incomplete; or 2) identify a nearby location where the service *can* route to.
161 | In this case we will take option 1.
162 | Before we remove the offending line 32 from the analysis, we will join the data from the desire lines back onto the results:
163 |
164 | ```{r}
165 | routes = sf::st_sf(
166 | cbind(sf::st_drop_geometry(santiago_routes_cs),
167 | sf::st_drop_geometry(desire_lines)),
168 | geometry = santiago_routes_cs$geometry
169 | )
170 | ```
171 |
172 | Update results...
173 |
174 | ```{r}
175 | routes$godutch_slc = round(routes$godutch_pcycle * routes$all)
176 | rnet = stplanr::overline2(routes, "godutch_slc")
177 | plot(rnet, lwd = rnet$godutch_slc / mean(rnet$godutch_slc))
178 | # library(tmap)
179 | # tmap_mode("view")
180 | # tm_shape(rnet) +
181 | # tm_lines(lwd = "godutch_slc", scale = 9)
182 | ```
183 |
184 |
185 | ## Next steps
186 |
187 | Clearly to do this in a production environment we would use a larger dataset, but the concepts would be the same.
188 | We would refine the method in multiple ways.
189 | The next basic step, however, would be to convert the straight desire lines into routes, to calculate more accurate distance and hilliness levels for each OD pair.
190 | Then we would be able to create a route network to help prioritise cycling across the city.
191 |
192 |
193 | ```{r, eval=FALSE}
194 | route_segments_1_5 = route(l = desire_lines[1:5, ], route_fun = cyclestreets::journey)
195 | mapview::mapview(route_segments_1_5)
196 | ```
197 |
--------------------------------------------------------------------------------
/vignettes/refs.bib:
--------------------------------------------------------------------------------
1 | @TechReport{department_for_transport_national_2016,
2 | type = {Active {Travel}},
3 | title = {National {Propensity} to {Cycle} {Tool} {Project}: full report with annexes},
4 | url = {https://www.gov.uk/government/publications/national-propensity-to-cycle-first-phase-development-study},
5 | institution = {Department for Transport},
6 | author = {{Department for Transport}},
7 | year = {2016},
8 | }
9 |
10 | @TechReport{department_for_transport_local_2017,
11 | title = {Local {Cycling} and {Walking} {Infrastructure} {Plans}},
12 | url = {https://assets.publishing.service.gov.uk/government/uploads/system/uploads/attachment_data/file/607016/cycling-walking-infrastructure-technical-guidance.pdf},
13 | urldate = {2019-03-24TZ},
14 | institution = {Department for Transport},
15 | author = {{Department for Transport}},
16 | year = {2017},
17 | }
18 |
19 | @Article{goodman_scenarios_2019,
20 | title = {Scenarios of cycling to school in {England}, and associated health and carbon impacts: {Application} of the ‘{Propensity} to {Cycle} {Tool}’},
21 | volume = {12},
22 | issn = {2214-1405},
23 | shorttitle = {Scenarios of cycling to school in {England}, and associated health and carbon impacts},
24 | url = {http://www.sciencedirect.com/science/article/pii/S2214140518301257},
25 | doi = {10.1016/j.jth.2019.01.008},
26 | abstract = {Background
27 | The Propensity to Cycle Tool (PCT) is a freely available, interactive tool help prioritise cycling initially launched in England in 2017 and based on adult commuting data. This paper applies the method to travel to school data, and assesses health and carbon benefits based on nationwide scenarios of cycling uptake.
28 | Methods
29 | The 2011 National School Census provides origin-destination data for all state-funded schools in England (N = 7,442,532 children aged 2–18 in 21,443 schools). Using this dataset, we modelled propensity to cycle as a function of route distance and hilliness between home and school. We generated scenarios, including ‘Go Dutch’ – in which English children were as likely to cycle as Dutch children, accounting for trip distance and hilliness. We estimated changes in the level of cycling, walking, and driving, and associated impacts on physical activity and carbon emissions.
30 | Results
31 | In 2011, 1.8\% of children cycled to school (1.0\% in primary school, 2.7\% in secondary school). If Dutch levels of cycling were reached, under the Go Dutch scenario, this would rise to 41.0\%, a 22-fold increase. This is larger than the 6-fold increase in Go Dutch for adult commuting. This would increase total physical activity among pupils by 57\%, and reduce transport-related carbon emissions by 81 kilotonnes/year. These impacts would be substantially larger in secondary schools than primary schools (a 96\% vs. 9\% increase in physical activity, respectively).
32 | Conclusion
33 | Cycling to school is uncommon in England compared with other Northern European countries. Trip distances and hilliness alone cannot explain the difference, suggesting substantial unmet potential. We show that policies resulting in substantial uptake of cycling to school would have important health and environmental benefits. At the level of road networks, the results can inform local investment in safe routes to school to help realise these potential benefits.},
34 | urldate = {2019-03-04TZ},
35 | journal = {Journal of Transport \& Health},
36 | author = {Anna Goodman and Ilan Fridman Rojas and James Woodcock and Rachel Aldred and Nikolai Berkoff and Malcolm Morgan and Ali Abbas and Robin Lovelace},
37 | month = {mar},
38 | year = {2019},
39 | keywords = {Active travel, Carbon emissions, Cycling, Modelling, Physical activity, School},
40 | pages = {263--278},
41 | }
42 |
43 | @Article{lovelace_propensity_2017,
44 | title = {The {Propensity} to {Cycle} {Tool}: {An} open source online system for sustainable transport planning},
45 | volume = {10},
46 | copyright = {Copyright (c) 2016 Robin Lovelace, Anna Goodman, Rachel Aldred, Nikolai Berkoff, Ali Abbas, James Woodcock},
47 | issn = {1938-7849},
48 | shorttitle = {The {Propensity} to {Cycle} {Tool}},
49 | url = {https://www.jtlu.org/index.php/jtlu/article/view/862},
50 | doi = {10.5198/jtlu.2016.862},
51 | abstract = {Getting people cycling is an increasingly common objective in transport planning institutions worldwide. A growing evidence base indicates that high quality infrastructure can boost local cycling rates. Yet for infrastructure and other cycling measures to be effective, it is important to intervene in the right places, such as along ‘desire lines’ of high latent demand. This creates the need for tools and methods to help answer the question ‘where to build?’. Following a brief review of the policy and research context related to this question, this paper describes the design, features and potential applications of such a tool. The Propensity to Cycle Tool (PCT) is an online, interactive planning support system that was initially developed to explore and map cycling potential across England (see www.pct.bike). Based on origin-destination data it models cycling levels at area, desire line, route and route network levels, for current levels of cycling, and for scenario-based ‘cycling futures.’ Four scenarios are presented, including ‘Go Dutch’ and ‘Ebikes,’ which explore what would happen if English people had the same propensity to cycle as Dutch people and the potential impact of electric cycles on cycling uptake. The cost effectiveness of investment depends not only on the number of additional trips cycled, but on wider impacts such as health and carbon benefits. The PCT reports these at area, desire line, and route level for each scenario. The PCT is open source, facilitating the creation of scenarios and deployment in new contexts. We conclude that the PCT illustrates the potential of online tools to inform transport decisions and raises the wider issue of how models should be used in transport planning.},
52 | language = {en},
53 | number = {1},
54 | urldate = {2017-06-01TZ},
55 | journal = {Journal of Transport and Land Use},
56 | author = {Robin Lovelace and Anna Goodman and Rachel Aldred and Nikolai Berkoff and Ali Abbas and James Woodcock},
57 | month = {jan},
58 | year = {2017},
59 | note = {bibtex:lovelace\_propensity\_2017},
60 | keywords = {Cycling, Participatory, Planning, modelling},
61 | }
62 |
--------------------------------------------------------------------------------
/vignettes/uk-cities.Rmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Reproducing cycling potential estimates in UK cities"
3 | output: rmarkdown::html_vignette
4 | vignette: >
5 | %\VignetteIndexEntry{Reproducing cycling potential estimates in UK cities}
6 | %\VignetteEngine{knitr::rmarkdown}
7 | %\VignetteEncoding{UTF-8}
8 | author:
9 | - "Nathanael Sheehan"
10 | ---
11 |
12 | ```{r, include = FALSE}
13 | knitr::opts_chunk$set(
14 | collapse = TRUE,
15 | comment = "#>"
16 | )
17 | ```
18 |
19 | Where is cycle infrastructure most needed in UK cities? Clear answers can fundamentally change our built environment and support national initiatives to build a more sustainable future. With the aim of enabling cycling uptake, the PCT project provides transport planners, policy-makers and academics with free tools to prioritise investments and interventions.
20 |
21 | Evidence-based interventions can make streets safer for future generations.
22 | This article demonstrates how to retrieve cycling potential data for any UK city, down to the route network level (see the `cycling-potential-uk` [here](https://itsleeds.github.io/pct/articles/cycling-potential-uk.html) or by running [`vignette("cycling-potential-uk")`](https://itsleeds.github.io/pct/articles/cycling-potential-uk.html) in R for a tutorial showing how the package can provide cycling uptake estimates at the area level), and how to use the results to see which streets will have high potential.
23 | These results can help prioritise investment in new cycleways and other interventions.
24 |
25 | Set `eval=TRUE` to run this code when knitting:
26 |
27 | ```{r}
28 | knitr::opts_chunk$set(eval = FALSE)
29 | ```
30 |
31 | # Prerequisites
32 |
33 | The following packages must be installed and loaded to run the code in this vignette.
34 |
35 | ```{r setup, message=FALSE, warning=FALSE}
36 | library(pct)
37 | library(dplyr)
38 | library(sf)
39 | library(tmap)
40 | ```
41 |
42 | # Picking a study area
43 |
44 | ## Part A) Choosing a region
45 |
46 | Exploring study areas with PCT can be achieved by running `view(pct_regions)` in the R console. `pct_regions` are based on ‘regions’ from the geographic structure for England [(ONS)](https://www.ons.gov.uk/methodology/geography/ukgeographies/administrativegeography/england). Formerly known as Government offices for the regions or GOR’s (established in 1994), regions reflect a number of government departments who work with their local community to maximise prosperity and the quality of life within their area. Northern Ireland, Scotland and Wales were not subdivided into GOR’s but are listed with them for UK wide statistics.
47 |
48 | Based on data from the most recent census (2011), PCT provides spatial and travel data for all 45 regions across England and Wales. To begin with, this example will demonstrate the PCT method for the city of Cardiff which belongs to the region of Wales.
49 |
50 | ```{r}
51 | region_name = "wales"
52 | zones_all = get_pct_zones(region_name)
53 | ```
54 |
55 | ## Part A) Picking a Local Authority
56 |
57 | Each region in England and Wales is composed of multiple local authorities. Among other things, each local authority takes the lead for local planning, housing and environmental health.
58 |
59 | How do you find all the local authorities part of your region?
60 | ```{r include=TRUE}
61 | unique(zones_all$lad_name)
62 | ```
63 |
64 | Aha! As we can see Wales is composed of 42 local authorities. As we are looking at Cardiff in this example, we should declare that as our ```la_name```.
65 | ```{r}
66 | la_name = "Cardiff"
67 | ```
68 |
69 | # Plotting Current Cycle Uptake
70 |
71 | Now we have chosen our region and city, we can easily plot the total number of cyclists based on the 2011 census.
72 | ```{r include=TRUE, fig.align='center', fig.width = 7, fig.height = 6}
73 | zones = zones_all %>%
74 | filter(lad_name == la_name)
75 | plot(zones["bicycle"])
76 | ```
77 |
78 | TaDa! The plot shows us that cycling is most prominent within the centre of Cardiff. While this is a first step in understanding where new cycle infrastructure is needed, it doesn't outline the road network where new demand is likely to occur.
79 |
80 | # Plotting New Demand Based On PCT Models
81 |
82 | PCT provides an easy way to get road network data for any ```pct_region```. The road network data can then be filtered to the zones within our local authority.
83 | ```{r}
84 | rnet_all = pct::get_pct_rnet(region_name)
85 | rnet = rnet_all[zones, ]
86 | ```
87 |
88 | With our road network data fitted to our study area, we are now ready to plot where investment should be prioritised based on a demand model. PCT is built with numerous demand models based on varying situations (e.g. `govtarget_slc`,`gendereq_slc` and `ebike_slc`. In this example, we use the `go dutch` demand model; where demand is modelled on a cycle uptake equivalent to that in the Netherlands.
89 |
90 | ```{r include=TRUE, fig.align='center', fig.width = 7, fig.height = 6}
91 | plot(zones$geometry)
92 | plot(rnet["dutch_slc"], add = TRUE)
93 | ```
94 |
95 | Voila! The blue lines represent the road network with colour proportional to estimated potential based on the go dutch model. This plot helps us understand where to prioritise cycle infrastructure and what a new demand may look like.
96 |
97 | # Comparing Two Cities
98 |
99 | Now we have seen the ease and versatility the PCT package provides, we can now use the method to explore more cities. Take Devon for example, the region has two major cities Exeter and Plymouth. Both cities obtain major universities, growing industries and have a relatively low cycle uptake. The latter should change, and the PCT package can provide the tools to help that.
100 |
101 | We can now wrap the method we used for Cardiff into a function in order to compare the differences between the two cities.
102 |
103 | ```{r}
104 | pct_zones_rnet = function(la_name, region_name = "devon") {
105 | zones_all = pct::get_pct_zones(region_name)
106 | zones = zones_all %>%
107 | filter(lad_name == la_name)
108 | plot(zones["bicycle"])
109 | rnet_all = pct::get_pct_rnet(region_name)
110 | rnet = rnet_all[zones, ]
111 | plot(zones$geometry)
112 | plot(rnet["dutch_slc"], add = TRUE)
113 | list(zones = zones, rnet = rnet)
114 | }
115 |
116 | plymouth_results = pct_zones_rnet(la_name = "Plymouth")
117 | exeter_results = pct_zones_rnet(la_name = "Exeter")
118 | ```
119 |
120 |
121 | Nice! The plots indicate a spatial spread for cycling in Plymouth, with investment necessary not only in the centre of the city. While for Exeter the distribution remains monocentric, with investment necessary mostly in the centre.
122 |
123 | We can create side-by-side interactive maps of the route network potential for of same cities for a more detailed comparison as follow:
124 |
125 | ```{r}
126 | tmap_mode("view")
127 | b = c(0, 100, 200, 500, 1000)
128 | m1 = tm_shape(plymouth_results$rnet) +
129 | tm_lines("dutch_slc", breaks = b, palette = "viridis", lwd = 2) +
130 | tm_scale_bar()
131 | m2 = tm_shape(exeter_results$rnet) +
132 | tm_lines("dutch_slc", breaks = b, palette = "viridis", lwd = 2) +
133 | tm_scale_bar()
134 | tmap_arrange(m1, m2, ncol = 2)
135 | ```
136 |
137 | # Conclusions and next steps
138 |
139 | As demonstrated, the PCT package provides an easy way to understand current cycle statistics and potential cycle uptake in any UK city. The methods used in this article can be used for planning future cycle infrastructure and can be expanded on using the other methods part of the PCT package. If this article is of use/interest, why not try for your local region showing the potential based on different models.
140 | You can also try the following resources (in R and online):
141 |
142 | - Have a play with the [PCT web application](https://www.pct.bike/)
143 | - For more of a deep dive into the methods, see the [`pct_training`](https://itsleeds.github.io/pct/articles/pct_training.html) vignette
144 | - See the [`pct-international`](https://itsleeds.github.io/pct/articles/pct-international.html) to see how to apply the methods internationally
145 |
146 |
147 | We're interested to know how you've used the methods/data so please get in touch.
--------------------------------------------------------------------------------