Alon Levy recently published the this blog post on Eric Goldwyn and Alon Levy’s proposed Brooklyn bus system redesign. The two authors are both prominent researchers in public transit. I particularly enjoy Alon Levy’s blog’s series on tracking how much more urban public transit infrastructure development costs in the US versus everywhere else in the world. You can find that body of work, here.
This post will be notes on taking the proposed network they outlined and converting to a graph representation. With this representation, it will be easy to perform comparative analyses on it compared to, say, the current transit network in Brooklyn and see how it increases of decreases transit accessibility.
The bus redesign
I would suggest reading the blog post for details but, in summary, the system redesign drops most routes, makes new lines that are “evenly spaced” through the system, and increases frequency on each of those lines. You can see a KML of the proposed map, here.
Above: Screen capture of the proposed network.
The goal is to convert this outlined network into a TransitJSON for consumption by peartree. You can read more about peartree at its Github repository. You can read more about how the TransitJSON works in this pull request on that repository.
Essentially, TransitJSON is a GeoJSON
FeatureCollection with a set of required parameters under each
To do this, we first convert the KML to a GeoJSON. Mapbox has created a library to do this already, to
toGeoJSON. In this case, I just used their static site hosted on that repository and cut and pasted the KML in since it was really small.
Transform operation (part 1)
We need to do the following:
- Read in the JSON of the KML
- Convert it to a tabular structure
- Parse the headway for the name if available (held in brackets)
- Drop lines that are Queens lines (Manhattan and Grand lines)
- Cast in EPSG 4326 project (default degrees) and then convert to equal area
The resulting Geopandas GeoDataFrame will be able to plot the following line:
Above image simply plotted with the following:
Transform operation (part 2)
Because the stops were not tagged in the KML or grouped with a specific line, we need to impute this. We can do this through a quick spatial operation, by joining all route-adjacent stops that are within a certain threshold of the line.
All we need to do is:
- Make sure that the stops and lines are in the same projection
- Tag the stops as related to that route
- Buffer the stops and intersect with the line to break the line into segments
- Use the resulting segments to get the stop order (so that we know which stops comes after the next)
- Submit the sorted and ordered stops into a tabular DataFrame
This work can be accomplished like so:
Assembly of transformed components
We now have a routes and stops table. From these two, we can work through the routes and assembly the related stops (ordered, now) for each route, converting the data into a TransitJSON format:
Loading into a graph
From here on out, we can just use peartree utilities. We can load the TransitJSON into peartree easily - and it will identify the segments and convert the summary TransitJSON data into a NetworkX graph in one line:
Once we have that object, we can plot it, perform accessibility analyses with it, whatever we want.
Here is what the network looks like, plotted (akin to our previous plot):
In a previous post I computed the betweenness centrality (BC) of the current Brooklyn bus network. I am just going to repeat that same calculation method here and visualize what the old and new BC results look like (including code to generate below for reference):
Old system, from previous post:
New proposed system:
What is immediately visible is that the system is significantly more balanced overall. As a result, the network features a much more balanced level of centrality along its graph nodes. In part, that is also achieved through more sparse network connections. Higher frequencies along all routes, though, reduced segment impedance and thus contributes greatly to less reliance on single thoroughfares (such as Flatbush).
Code to generate:
A quick win would be to get some employment and housing data (the company I work for, UrbanFootprint happens to have a highly accurate canvas of this for the whole country, and calculate network accessibility on the current system and the future system (actually quite easy to do in UrbanFootprint, so maybe could do the rest of this work in an existing application…).