- Background
- Using stplanr
- Future plans
2017-04-27

Common computational tasks in transportation planning:
Transport planning is notoriously reliant on 'black boxes' and the same applies to scientific research into transport systems [@Waddell2002].
stplanr seeks to address these issues.
stplanr lives here: https://github.com/ropensci/stplanr
Package can be installed from CRAN or GitHub (see the package's README for details), it can be loaded in with library():
install.packages("stplanr") # stable CRAN version
# devtools::install_github("ropensci/stplanr") # dev version
library(stplanr) # also loads spatial package
## Loading required package: sp
Use
@importFromwhenever possible. Right now you haveimport(openxlsx)andimport(sp)in your NAMESPACE file. Just import the functions you need. Same for other pkg deps.
Tests: Pleae write tests to cover at least all the major functions before we accept. Use
testthat::skip_on_cran()for any tests that do web requests, so that CRAN tests don't fail in case a service is temporarily down
I think token's can be a bit easier for the user. Right now you have e.g.,
if (!Sys.getenv('CYCLESTREET') == "") {
cckey <- Sys.getenv('CYCLESTREET')
}
if(is.null(cckey)){
stop("You must have a CycleStreets.net api key saved as 'cckey'")
}
| cents | SpatialPointsDataFrame.of.home.locations.for.flow.analysis. |
|---|---|
| destination_zones | example destinations data |
| destinations | example destinations data |
| flow | data frame of commuter flows |
| flow_dests | data frame of invented commuter flows with destinations in a different layer than the origins |
| flowlines | SpatialLinesDataFrame of commuter flows |
| routes_fast | SpatialLinesDataFrame of commuter flows on the travel network |
| routes_slow | SpatialLinesDataFrame of commuter flows on the travel network |
| zones | SpatialPolygonsDataFrame of home locations for flow analysis. |
data("flow", package = "stplanr")
head(flow[c(1:3, 12)])
## Area.of.residence Area.of.workplace All Bicycle ## 920573 E02002361 E02002361 109 2 ## 920575 E02002361 E02002363 38 0 ## 920578 E02002361 E02002367 10 0 ## 920582 E02002361 E02002371 44 3 ## 920587 E02002361 E02002377 34 0 ## 920591 E02002361 E02002382 7 0
data("cents", package = "stplanr")
as.data.frame(cents[1:3,-c(3,4)])
## geo_code MSOA11NM coords.x1 coords.x2 ## 1708 E02002384 Leeds 055 -1.546463 53.80952 ## 1712 E02002382 Leeds 053 -1.511861 53.81161 ## 1805 E02002393 Leeds 064 -1.524205 53.80410
flow_single_line = flow[4,] # select only the first line desire_line_single = od2line(flow = flow_single_line, zones = cents) plot(cents) plot(desire_line_single, add = T)
flow[4,])od2line() matched the cents matching the lines and created a line (the hard bit)od2line
## function (flow, zones, destinations = NULL, zone_code = names(zones)[1],
## origin_code = names(flow)[1], dest_code = names(flow)[2],
## zone_code_d = NA, silent = TRUE)
## {
## l <- vector("list", nrow(flow))
## if (is.null(destinations)) {
## if (!silent) {
## message(paste("Matching", zone_code, "in the zones to",
## origin_code, "and", dest_code, "for origins and destinations respectively"))
## }
## for (i in 1:nrow(flow)) {
## from <- zones@data[[zone_code]] %in% flow[[origin_code]][i]
## if (sum(from) == 0)
## warning(paste0("No match for line ", i))
## to <- zones@data[[zone_code]] %in% flow[[dest_code]][i]
## if (sum(to) == 0 & sum(from) == 1)
## warning(paste0("No match for line ", i))
## x <- sp::coordinates(zones[from, ])
## y <- sp::coordinates(zones[to, ])
## l[[i]] <- sp::Lines(list(sp::Line(rbind(x, y))),
## as.character(i))
## }
## }
## else {
## if (is.na(zone_code_d)) {
## zone_code_d <- names(destinations)[1]
## }
## if (!silent) {
## message(paste("Matching", zone_code, "in the zones and",
## zone_code_d, "in the destinations,\nto", origin_code,
## "and", dest_code, "for origins and destinations respectively"))
## }
## for (i in 1:nrow(flow)) {
## from <- zones@data[[zone_code]] %in% flow[[origin_code]][i]
## if (sum(from) == 0)
## warning(paste0("No match for line ", i))
## to <- destinations@data[[zone_code_d]] %in% flow[[dest_code]][i]
## if (sum(to) == 0 & sum(from) == 1)
## warning(paste0("No match for line ", i))
## x <- sp::coordinates(zones[from, ])
## y <- sp::coordinates(destinations[to, ])
## l[[i]] <- sp::Lines(list(sp::Line(rbind(x, y))),
## as.character(i))
## }
## }
## l <- sp::SpatialLines(l)
## l <- sp::SpatialLinesDataFrame(l, data = flow, match.ID = FALSE)
## sp::proj4string(l) <- sp::proj4string(zones)
## l
## }
## <environment: namespace:stplanr>
o = cents[cents$geo_code %in% flow$Area.of.residence[4],] d = cents[cents$geo_code %in% flow$Area.of.workplace[4],] l_single = Lines(list(Line(rbind(o@coords, d@coords))), ID = 1) l_sp = SpatialLines(LinesList = list(l_single))
plot(cents) points(o, cex = 5) points(d, cex = 5) flow[4, 1:3]
## Area.of.residence Area.of.workplace All ## 920582 E02002361 E02002371 44
plot(l_sp, add = TRUE)
l <- od2line(flow = flow, zones = cents) # remove lines with no length l <- l[!l$Area.of.residence == l$Area.of.workplace,] plot(l, lwd = l$All / 10)
stplanr has various functions for route allocation:
route_cyclestreet() # UK, cycling route_graphhopper() # worldwide, any mode route_transportapi_public() # UK, public transport viaroute() # worldwide, any mode
library(leaflet) leaflet() %>% addTiles() %>% addPolylines(data = r)
routes_fast = line2route(l = l)
plot(l) plot(routes_fast, add = T, col = "red")
devtools::install_github("ropensci/stplanr")
vignette("introducing-stplanr")
od2line(flow = flow[12,], zones = cents)
flowlines object using tmap with different colours and widthsflowlines and visualise these (tricky)flowlines object (advanced)