Author: Geoff Boeing
NetworkX is ubiquitous, easy to use, and sufficiently fast for most use cases. But it can be slow for analyzing very large graphs because it is pure Python, trading off speed for ease of use. Fortunately, converting OSMnx-created NetworkX graphs to other graph libraries' types is relatively quick and simple and makes analysis much faster for those use cases where it's needed. For example, you might consider converting your NetworkX graph to igraph, graph-tool, or cugraph for analysis. This example demonstrates igraph.
First install igraph or run Jupyter from the Docker container (which already has it installed along with OSMnx and NetworkX).
import operator
import igraph as ig
import networkx as nx
import numpy as np
import osmnx as ox
%matplotlib inline
print(ox.__version__)
print(ig.__version__)
weight = "length"
# create networkx graph
G_nx = ox.graph_from_place("Piedmont, CA, USA", network_type="drive")
osmids = list(G_nx.nodes)
G_nx = nx.relabel.convert_node_labels_to_integers(G_nx)
# give each node its original osmid as attribute since we relabeled them
osmid_values = {k: v for k, v in zip(G_nx.nodes, osmids)}
nx.set_node_attributes(G_nx, osmid_values, "osmid")
%%time
# convert networkx graph to igraph
G_ig = ig.Graph(directed=True)
G_ig.add_vertices(G_nx.nodes)
G_ig.add_edges(G_nx.edges())
G_ig.vs["osmid"] = osmids
G_ig.es[weight] = list(nx.get_edge_attributes(G_nx, weight).values())
assert len(G_nx.nodes()) == G_ig.vcount()
assert len(G_nx.edges()) == G_ig.ecount()
source = list(G_nx.nodes())[0]
target = list(G_nx.nodes())[-1]
%%time
path1 = G_ig.get_shortest_paths(v=source, to=target, weights=weight)[0]
%%time
path2 = nx.shortest_path(G_nx, source, target, weight=weight)
assert path1 == path2
%%time
path_length1 = G_ig.shortest_paths(source=source, target=target, weights=weight)[0][0]
%%time
path_length2 = nx.shortest_path_length(G_nx, source, target, weight)
assert path_length1 == path_length2
%%time
closeness1 = G_ig.closeness(vertices=None, mode="ALL", cutoff=None, weights=weight, normalized=True)
max_closeness1 = np.argmax(closeness1)
%%time
closeness2 = nx.closeness_centrality(G_nx, distance=weight, wf_improved=True)
max_closeness2 = max(closeness2.items(), key=operator.itemgetter(1))[0]
# confirm same node has max closeness in both graphs
assert G_nx.nodes[max_closeness2]["osmid"] == G_ig.vs[max_closeness1]["osmid"]