Calculating Betweenness Centrality using Python#

import networkx as nx
import osmnx as ox
import pandas as pd
import geopandas as gpd
ox.config(use_cache=True, log_console=True)
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
Cell In[1], line 1
----> 1 import networkx as nx
      2 import osmnx as ox
      3 import pandas as pd

ModuleNotFoundError: No module named 'networkx'

Download OSM data for a specific place

graph = ox.graph_from_place('Heidelberg, Germany', network_type='drive')

Plot the graph

fig, ax = ox.plot_graph(graph, node_size=5)

Centrality#

Calculate betweenness centrality using the shortest routes (i.e. weight='length' means that we use the length of each edge).

betweenness_centrality = nx.edge_betweenness_centrality(graph, weight="length")

Convert the values in betweenness_centrality into a pandas.Dataframe.

centrality_df = pd.DataFrame(index=betweenness_centrality.keys(), data=betweenness_centrality.values())

Name the two index columns of the centrality_df ‘u’ and ‘v’.

centrality_df.reset_index(inplace=True)
centrality_df.columns = ['u', 'v', 'key', 'centrality']
centrality_df = centrality_df.set_index(['u', 'v', 'key'])

Converting the graph to a geopandas.GeoDataFrame yields two dataframes. One for the nodes, and one for the edges.

nodes_df, edges_df = ox.graph_to_gdfs(graph)

Join the centrality_df with the edges_df.

centrality_gdf = centrality_df.join(edges_df[['osmid', 'geometry']])
centrality_gdf = gpd.GeoDataFrame(centrality_gdf, crs=4326)

Now that the centrality values have been joined with the edges which include the geometries, we can plot the centrality values of the road network on a map using the geopandas.explore() function.

centrality_gdf.explore(column='centrality', cmap='magma_r', tiles='cartodbpositron')

Betweenness centrality using the fastest routes#

Calculate centrality using the fastest route instead of the shortest route.

  1. Assign travel speed values to each edge using the ox.add_edge_speeds function. Fill in the missing road types in the dictionary below based on the openrouteservice documetation on travel speeds.

hwy_speeds = {'motorway': 130,
              'trunk': 100,
              'residential': 60,
              'tertiary': 60} #etc
graph_with_speeds = ox.add_edge_speeds(graph, hwy_speeds)
  1. Calculate the travel time for each edge using the ox.add_edge_travel_times function.

  1. Calculate betweenness centrality again using the nx.edge_betweenness_centrality but pass weight="travel_time as an argument.

betweenness_centrality_time = nx.edge_betweenness_centrality(graph, weight="travel_time")
  1. Convert the centrality value to a pandas.DataFrame and join it with the edges_df dataframe as above and visualize the result in a map.

Geographically adapted betweenness centrality#

  1. Get start and destination nodes in the graph from geographic coordinates using the nearest_nodes function.

origin_node =
destination_node =
  1. Calculate route between the two nodes using the ox.shortest_path() function.

  1. Plot the route using

fig, ax = ox.plot_graph_route(graph, route, route_color="y", route_linewidth=6, node_size=0)
  1. Convert the route to a geopandas.GeoDataFrame using the ox.utils_graph.route_to_gdf.

  1. Generate 100 routes by choosing random start and endpoints.

  1. Merge all route dataframes using the pd.concat function

  1. Calculate betweenness centrality indicator of the graph by grouping the routes by the columns ‘u’, ‘v’ and ‘key’ and counting the number of features.

  1. Join the dataframe containing the manually computed centrality values with the edges_df dataframe. Plot the manually computed betweenness centrality on an interactive map.

Bonus#

Write a function which chooses a start and destination node from the graph based on the population distribution from the Global Human Settlement population layer.