-
Notifications
You must be signed in to change notification settings - Fork 2
/
transport-workshop.Rmd
262 lines (201 loc) · 11.4 KB
/
transport-workshop.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
---
title: "Route Analysis using R and Google Maps"
output: pdf_document
---
# Setup
Open up R Studio (click **Start > All Programs > RStudio > RStudio** or double-click the icon on the desktop).
You don't need any data to run this tutorial - we generate it all
online. However, it is good practice to set-up a new project
for our R routing experiments. Do this in RStudio now (if you're new to
RStudio, take a look around and you'll soon see how).
All but one of the libraries (**stplanr**)
we will use in this package can be downloaded
from CRAN, R's online store of packages.
- **ggmap**: a package for plotting geographical data
- **sp**: a package defining spatial objects in R
- **devtools**: a package we'll use to install **stplanr**!
All the packages can be installed
by clicking **Tools > Install Packages**. Alternatively you
can install these packages with the following commands:
```{r, eval=FALSE}
pkgs <- c("ggmap", "sp", "devtools") # create an object for the packages
install.packages(pkgs) # install the packages - requires the internet
```
**ggmap** allows for quick and easy map creation and an
interface to Google Maps within R.
First, we need to load the library, so type into the console:
```{r, comment=NA, message=FALSE, warning=FALSE}
library(ggmap) # use install.packages("ggmap") if not already installed
```
This will also load various other libraries and you will probably see information messages. We can then create a quick map of Leeds with the `qmap()` function. You should see the map appear in the 'Plots' window to the right of the R Studio window.
```{r, comment=NA, message = FALSE}
qmap('Leeds')
```
We can also search for anything we would search for in the Google Maps search box - e.g. different locations, or postcodes. For example, try:
```{r, comment=NA, message = FALSE, eval=FALSE}
qmap('LS2 9JT')
```
Try different postcodes or locations to search for, and see what happens. You will see that the scale of the map stays the same - this is fine for Leeds, but of limited use for somewhere smaller (like Norwich) or larger (like Ireland). The default zoom is level 10, but we can change this to something more useful. Higher numbers zoom in more (i.e. show a smaller area). Try:
```{r, comment=NA, message = FALSE, eval=FALSE}
qmap('LS2 9JT', zoom = 17)
```
This shows us the map centred on the Parkinson building (although it isn't marked on the map).
As well as the maps layer, we can access the satellite and hybrid map types from Google Maps:
```{r, comment=NA, message = FALSE, eval = FALSE}
qmap('LS2 9JT', zoom = 17, maptype = 'satellite')
```
One useful shortcut when using R Studio (or R on its own) is that pressing the 'up' key on the keyboard will show your previous command. You can then edit this and press return to run it, which avoids the need to type the whole command out again! Try it with the command below:
```{r, comment=NA, message = FALSE, eval=FALSE}
qmap('LS2 9JT', zoom = 17, maptype = 'hybrid')
```
# Routing
Just as you can get directions from the Google Maps website, you can also access the same tools through the API. The code below passes an origin and destination to the routing command and then shows the route on a map. Try running this code, and then try changing to origin and/or destination and try running it again. You may need to adjust the location of the map to show the whole route.
```{r, comment = NA, message = FALSE, warning=FALSE, echo = FALSE}
from <- 'Leeds station, New Station Street, Leeds LS1 5DL, United Kingdom'
to <- 'LS2 9JT'
route_df <- route(from, to, structure = 'route', mode = 'walking')
qmap('Merrion Centre', zoom = 15) +
geom_path(
aes(x = lon, y = lat), colour = 'red', size = 1.5,
data = route_df, lineend = 'round')
```
With a bit of extra R code, we can create a data frame of different origin and destination pairs, and then write the code to get R to look through the API and produce a route for each of these.
First of all, add the code to get R to save the map as a PDF. Run this code, and R will save the map as a PDF file in your working folder. (Run `getwd()` if you are not sure where your working folder is).
```{r, comment = NA, message = FALSE, warning=FALSE, eval=FALSE}
#save as PDF
pdf(file="image.pdf")
from <- 'Leeds station, New Station Street, Leeds LS1 5DL, United Kingdom'
to <- 'LS2 9JT'
route_df <- route(from, to, structure = 'route', mode = 'walking')
qmap('Merrion Centre', zoom = 15) +
geom_path(
aes(x = lon, y = lat), colour = 'red', size = 1.5,
data = route_df, lineend = 'round')
#stop saving as PDF
dev.off()
```
Then we can add a data frame and a loop, to run the code for each entry.
```{r, comment = NA, message = FALSE, warning=FALSE, eval=FALSE}
#setup variable with list of origins
origins <- c("Leeds station, New Station Street, Leeds LS1 5DL","Leeds","Manchester",
"Manchester Oxford Road")
destinations <- c("LS2 9JT","Manchester","Liverpool","Manchester Picadilly")
map_center <- c("Merrion Centre","Marsden, UK","Warrington","Sackville St, Manchester")
zoom_level <- c(15,10,10,16)
#combine origins and destinations to create a data frame
df_orig_dest <- data.frame(origins,destinations,map_center,zoom_level)
#loop through for each map
for (i in 1:length(df_orig_dest)) {
#setup file name
filename <- paste0("route_",df_orig_dest[i,1],"_to_",df_orig_dest[i,2],".pdf")
#save as PDF and set file name
pdf(file=filename)
from <- as.character(df_orig_dest[i,1]) #check whether this is needed
to <- as.character(df_orig_dest[i,2])
route_df <- route(from, to, structure = 'route', mode = 'walking')
print(qmap(as.character(df_orig_dest[i,3]), zoom = df_orig_dest[i,4]) +
geom_path(
aes(x = lon, y = lat), colour = 'red', size = 1.5,
data = route_df, lineend = 'round'))
#stop saving as PDF
dev.off()
#end loop
}
```
Try experimenting with different parts of the code, to, for example, change the colour for each route, or add more entries. You can also save the maps as images - for example, type `?jpeg` into the console to see how to get the map as a JPEG.
```{r, echo=FALSE}
# Setup data for next section
origins <- c("Leeds station, New Station Street, Leeds LS1 5DL","Leeds","Manchester",
"Manchester Oxford Road")
destinations <- c("LS2 9JT","Manchester","Liverpool","Manchester Picadilly")
map_center <- c("Merrion Centre","Marsden, UK","Warrington","Sackville St, Manchester")
zoom_level <- c(15,10,10,16)
#combine origins and destinations to create a data frame
df_orig_dest <- data.frame(origins,destinations,map_center,zoom_level)
```
# Route Analysis
We have plotted a few maps now, but we can also do some analysis of the data as well. The variable `route_df` contains various pieces of information about the route we have plotted. Run `head(route_df)` to see the first six rows of this variable. The output may be slightly different if you have been experimenting with different routes.
```{r, comment = NA, message = FALSE, warning=FALSE, eval=FALSE}
head(route_df) #show the first six rows of route_df
```
We can add up the values from specific columns, using `colSums` to extract the total distance or time, for example.
```{r, comment = NA, message = FALSE, warning=FALSE, eval=FALSE}
colSums(route_df, na.rm = TRUE) #calc sum for each column, omitting missing values
```
Some of these values are just gibberish and mean nothing (e.g. `lat` and `lon`) but others are quite useful - total time or distance, for example. Distance is particularly useful, and is one that I used in my Home to School travel work.
Routes produced by Google Maps are useful, provide accurate indications
of route distance and reasonable estimates of times. You can even specify
what mode of transport through the *argument* `mode`.
(See what happens when you add `, mode = "bicycling"`: `walking` and
`driving` are the alternatives.)
However, the plotted routes do not follow the travel network, simply
snapping to key *nodes* where the road changes.
# Routing with CycleStreets.net
To overcome this problem, we can use alternative route finding services such as [graphhopper](https://graphhopper.com/) and
[osrm](http://project-osrm.org/). [CycleStreets](http://www.cyclestreets.net/)
is a routing service designed by cyclists for cyclists that we will use to illustrate
routing using other external services in R. It has various advantages over the
`route()` function (and some disadvantages) described above.
You need a CycleStreets.net 'API key'
for it to work.
For a project funded by
the UK's Department for Transport (DfT), an R interface to the CycleStreets.net
routing service has been created. This is included in the R package
**stplanr**. Let's download this package to reproduce the routes using CycleStreet.net.
```{r, eval=FALSE}
library(sp) # enables spatial data classes
library(devtools) # to install packages from github
install_github("robinlovelace/stplanr") # install the stplanr package
library(stplanr)
```
```{r}
cckey <- "79769a3a2d2a0caf" # add your API key
```
```{r, include=FALSE}
library(sp) # enables spatial data classes
library(stplanr)
```
## Convert the origin destination matrix into straight lines
To convert the text string origins and destinations into routes, we first
must convert them into objects of the `SpatialLinesDataFrame` data class:
```{r, message=FALSE}
# Extract the attribute data
f <- df_orig_dest[-3,]
# Set up coordinates
coords <- geocode(c(origins, destinations))
# Create SpatialLinesDataFrame
cents <- SpatialPointsDataFrame(coords = as.matrix(coords),
data = data.frame(code = c(origins, destinations)))
rlines <- gFlow2line(flow = f, zones = cents)
# Plot - uncomment to see result (delete the #)
# plot(rlines[1,], col = c("green", "red", "blue", "black"))
```
We have successfully saved our 'desire lines'. Now let's convert them
to navigable cycle routes and plot them:
```{r, eval = FALSE}
rquiet <- gLines2CyclePath(l = rlines, plan = "quietest")
plot(rquiet[1,]) # route from Leeds station to Leeds University (North - South)
plot(rquiet[2,]) # route from Leeds to Manchester!
```
```{r, echo=FALSE}
# save(rquiet, file = "rquiet.RData")
load("rquiet.RData")
```
To see the quietest cycling route from Manchester to Leeds we can
combine our **ggplot** skills with the new R object using fortify:
```{r}
rquiet_f <- fortify(rquiet)
bb <- make_bbox(lon = long, lat = lat, data = rquiet_f)
m1 <- ggmap(ggmap = get_map(location = bb))
m1 + geom_path(aes(x = long, y = lat, group = group), data = rquiet_f)
```
If you don't understand all the steps used in the above code block
do not despair: very few people do! All we can recommend is you continue
your 'journey' in R for transport applications by checking out
the references listed below.
# References
Bearman, N. (2015). Introduction to Using R for Spatial Analysis. Retrieved from http://www.nickbearman.me.uk/2015/01/introduction-to-using-r-for-spatial-analysis/
Kahle, D. and Wickham, H. ggmap: Spatial Visualization with ggplot2. The R Journal, 5(1), 144-161. URL: http://journal.r-project.org/archive/2013-1/kahle-wickham.pdf
Lovelace, R., & Cheshire, J. (2014). Introduction to visualising spatial data in R. National Centre for Research Methods Working Papers, 14(03). Retrieved from https://github.com/Robinlovelace/Creating-maps-in-R
# Further Information
This PDF was created on 11th April 2015 by Nick Bearman and Robin Lovelace for GIS for Transport Applications workshop (https://github.com/Robinlovelace/GIS4TA) at GISRUK 2015. It is available at https://github.com/nickbearman/transport-workshop.