Usage | 3. Existing bike network

This notebook explains how GrowBikeNet can extend an existing bike network.

Parameters covered: existing_network_spacing

We start every Usage notebook with the standard way of importing GrowBikeNet:

import growbikenet as gbn

Adding seed points on the existing bike network

So far GrowBikeNet was executed with the default parameter setting existing_network_spacing=None, which instructed GrowBikeNet to ignore existing bicycle infrastructure. This works for most cities, as existing infrastructure is usually negligible and one might as well just start from scratch. However, there are some cities with an already existing substantial network which would be useful to incorporate into the growth process. By calling GrowBikeNet with the parameter existing_network_spacing='auto' or with a positive integer, it will do exactly that.

In this case, the process of generating seed points is amended beforehand:

  • Consider all network components of the existing bike network that have a minimum length. This ensures that tiny, insignificant pieces are ignored.

  • On these components, choose a random first seed point.

  • Choose the closest seed point on the components that is at least existing_network_spacing meters away. The 'auto' option automatically chooses a recommended distance, at 50% of the seed_point_grid_spacing.

  • Proceed with the previous step until no more seed points can be placed on the components.

  • Now generate all the other seed points as usual, but do not consider seed points that are too close to already existing seed points.

Let us run GrowBikeNet on Athens, Greece with the existing_network_spacing='auto' option and observe the results:

edges_ordered = gbn.growbikenet("Municipality of Athens",
    existing_network_spacing='auto',)

The existing bike network is saved as multilinestring into the first row of the resulting geodataframe with several entries being None:

edges_ordered.head()
betweenness geometry source target ordering length length_cumulative
0 None MULTILINESTRING ((23.72545 37.97514, 23.72538 ... None None 0 22448 22448
1 0.162055 MULTILINESTRING ((23.74782 37.98344, 23.74766 ... 549525770.0 95663454.0 1 2768 25216
2 0.126482 MULTILINESTRING ((23.72891 37.98775, 23.72902 ... 6707879950.0 95663454.0 2 1632 26849
3 0.12253 LINESTRING (23.7278 37.95387, 23.72774 37.9541... 251136597.0 95663454.0 3 2426 29276
4 0.12253 LINESTRING (23.74782 37.98344, 23.74794 37.983... 6707879950.0 7229807073.0 4 2337 31613

To visualize the outcome, we plot first the existing bike network (first row) in blue, then the grown network (all other rows) in green. To add layer control in the top right of the map, we import folium:

Hide code cell source

import folium

viz = edges_ordered.iloc[:1].explore(
    tiles="CartoDB Positron",
    style_kwds={"weight": 2, "color": "#9999cc"},
    name="Existing bike network",
)
viz = edges_ordered.iloc[1:].explore(
    m=viz, 
    style_kwds={"weight": 3, "color": "#096a51"},
    name="Grown bike network",
)
folium.LayerControl().add_to(viz)
viz
Make this Notebook Trusted to load map: File -> Trust Notebook

Note how the short existing pieces in the northeast are ignored, but the other big enough components are incorporated into the growth process.

Comparing with growth from scratch

Let us add the outcome from growth from scratch (without the existing network) in orange to see the difference:

edges_ordered_from_scratch = gbn.growbikenet("Municipality of Athens")

Hide code cell source

viz = edges_ordered.iloc[:1].explore(
    tiles="CartoDB Positron",
    style_kwds={"weight": 2, "color": "#9999cc"},
    name="Existing bike network",
)
viz = edges_ordered_from_scratch.explore(
    m=viz, 
    style_kwds={"weight": 6, "color": "#f19730"},
    name="Grown bike network (from scratch)",
)
viz = edges_ordered.iloc[1:].explore(
    m=viz, 
    style_kwds={"weight": 3, "color": "#096a51"},
    name="Grown bike network (with existing network)",
)
folium.LayerControl().add_to(viz)
viz
Make this Notebook Trusted to load map: File -> Trust Notebook

In general, the network which accounts for existing infrastructure will be longer than the one grown from scratch, in this case

int((edges_ordered.iloc[-1].length_cumulative-
    edges_ordered.iloc[0].length_cumulative)/1000)
54

kilometers compared to

int((edges_ordered_from_scratch.iloc[-1].length_cumulative)/1000)
51

kilometers, as seed points are generated more densely.