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.
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)
Calculate the travel time for each edge using the
ox.add_edge_travel_times
function.
Calculate betweenness centrality again using the
nx.edge_betweenness_centrality
but passweight="travel_time
as an argument.
betweenness_centrality_time = nx.edge_betweenness_centrality(graph, weight="travel_time")
Convert the centrality value to a
pandas.DataFrame
and join it with theedges_df
dataframe as above and visualize the result in a map.
Geographically adapted betweenness centrality#
Get start and destination nodes in the graph from geographic coordinates using the
nearest_nodes
function.
origin_node =
destination_node =
Calculate route between the two nodes using the
ox.shortest_path()
function.
Plot the route using
fig, ax = ox.plot_graph_route(graph, route, route_color="y", route_linewidth=6, node_size=0)
Convert the route to a
geopandas.GeoDataFrame
using theox.utils_graph.route_to_gdf
.
Generate 100 routes by choosing random start and endpoints.
Merge all route dataframes using the
pd.concat
function
Calculate betweenness centrality indicator of the graph by grouping the routes by the columns ‘u’, ‘v’ and ‘key’ and counting the number of features.
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.