Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

NetworkX

Open in Colab

NetworkX is a Python package for dealing with complex networks (graphs). It provides Graph classes, graph algorithms, and visualization tools.

You may need to

(pycourse) conda install networkx
'2.5'

We’ll cover some basics in NetworkX. You can find additional information in the NetworkX documentation, which includes a tutorial.

First, let’s create a simple graph:

<Figure size 432x288 with 1 Axes>

Graph nodes can be any hashable object, which covers many things you might use

<Figure size 432x288 with 1 Axes>

You can also associate arbitrary data with each node and edge by passing in keyword arguments

<Figure size 432x288 with 1 Axes>
{'time': 2.0}
{('dog', 'cat'): 2.0}
{'dog': 'Rover', 'cat': 'Felix'}
{'dog': 10.0}

Generating Graphs

NetworkX provides Graph generators to generate a variety of random graphs.

Random Graphs

Erdos-Renyi Graphs

An Erdos-Renyi random graph Gn,pG_{n,p} is a graph on nn nodes, where the probability of an edge (i,j)(i,j) existing is pp. In NetworkX, this is called a gnp graph.

<Figure size 432x288 with 1 Axes>

Stochastic Block Models

A Graph generated from a stochastic block model (SBM) has kk clusters, and a k×kk\times k (symmetric) matrix PP of probabilities, where Pi,jP_{i,j} is the probability that a pair of nodes (a,b)(a,b) will be joined by an edge if aa is in cluster ii and bb is in cluster jj.

<Figure size 432x288 with 1 Axes>

Visualization

Visualizing graphs is often a great way to see and understand information.

Unless there is some “ground truth” way to lay out nodes (meaning each node has an associated coordinate), we must choose some way to place nodes in our visualization. There are a variety of methods for this.

Layouts

There are several layout methods you might use, which are good for certain applications.

Spectral Embeddings are good for partitioning the graph into clusters.

<Figure size 432x288 with 1 Axes>

Spring layouts tend to do a good job of separating nodes, which can be nice for visualization

<Figure size 432x288 with 1 Axes>

the Kamada-Kawai algorithm also gives visually pleasing results.

<Figure size 432x288 with 1 Axes>
{0: array([0.17110579, 0.96050409]), 1: array([-0.07340844, 0.39883311]), 2: array([-0.1636278 , 0.80843733]), 3: array([0.6557681 , 0.34205121]), 4: array([0.24983722, 0.66262339]), 5: array([0.66428275, 0.46626272]), 6: array([0.18279235, 0.50528361]), 7: array([-0.00311155, 0.72496871]), 8: array([0.45659536, 0.03043568]), 9: array([0.37525956, 0.70189348]), 10: array([-0.21879532, 0.62791278]), 11: array([0.37069697, 0.98009284]), 12: array([0.25848514, 0.27074475]), 13: array([0.50460278, 0.66928933]), 14: array([0.71199042, 0.66230768]), 15: array([0.58155124, 0.10662501]), 16: array([0.27799907, 0.49193621]), 17: array([0.32311994, 0.2392366 ]), 18: array([0.04597729, 0.34867528]), 19: array([0.40591381, 0.39122102]), 20: array([0.1402521 , 0.72953965]), 21: array([0.70020601, 0.03658417]), 22: array([0.52709292, 0.5576614 ]), 23: array([0.52252782, 0.82177566]), 24: array([0.82134001, 0.30528987]), 25: array([-0.53368525, -0.0098704 ]), 26: array([-0.42096579, 0.10067772]), 27: array([-0.52358375, -0.16721761]), 28: array([-1. , 0.12538073]), 29: array([-0.3029243 , -0.21589201]), 30: array([-0.23421812, 0.01156078]), 31: array([-0.64818868, -0.13952288]), 32: array([-0.75698617, 0.08511158]), 33: array([-0.78690368, -0.06417558]), 34: array([-0.74399632, -0.42400335]), 35: array([-0.82684009, -0.12782017]), 36: array([-0.94601317, -0.03558783]), 37: array([-0.83281379, -0.27244581]), 38: array([-0.3253795 , 0.51545033]), 39: array([-0.66515324, -0.25529943]), 40: array([-0.4672691 , 0.17548859]), 41: array([-0.57359166, 0.42224945]), 42: array([-0.9949458 , 0.44866723]), 43: array([-0.534468 , 0.30539691]), 44: array([-0.85281079, 0.18976326]), 45: array([-0.56340319, -0.48409942]), 46: array([-0.40202583, -0.38023752]), 47: array([-0.59452747, 0.15958976]), 48: array([-0.70329683, 0.29878521]), 49: array([-0.70492806, 0.41489023]), 50: array([ 0.72031485, -0.29968256]), 51: array([ 0.11775694, -0.70402689]), 52: array([ 0.33153675, -0.81225537]), 53: array([ 0.04177474, -0.33137769]), 54: array([ 0.56143996, -0.36084002]), 55: array([ 0.23535027, -0.53712185]), 56: array([ 0.25423092, -0.77793624]), 57: array([ 0.06792596, -0.81830562]), 58: array([ 0.57662783, -0.64210137]), 59: array([-0.15580042, -0.60891649]), 60: array([ 0.11649154, -0.3834705 ]), 61: array([ 0.40544559, -0.33738613]), 62: array([ 0.30263416, -0.16734182]), 63: array([ 0.94344243, -0.61761507]), 64: array([-0.06727787, -0.51977745]), 65: array([ 0.40420223, -0.69517689]), 66: array([ 0.39064416, -0.26508681]), 67: array([ 0.70705537, -0.59435424]), 68: array([ 0.37151636, -0.51377755]), 69: array([ 0.00633673, -0.93301984]), 70: array([-0.06702971, -0.69029724]), 71: array([ 0.45015611, -0.76124617]), 72: array([ 0.51211408, -0.47872145]), 73: array([ 0.06006509, -0.46173277]), 74: array([ 0.16351096, -0.20545729])}
<Figure size 432x288 with 1 Axes>

Algorithms

NetworkX implements a variety of graph algorithms.

Shortest Paths

A path between nodes xx and yy is a sequence of edges where the target of an edge is the source of the next edge.

(x,v0),(v0,v1),…,(vk,y)(x, v_0), (v_0, v_1), \dots, (v_k, y)

The length of the path is the number of edges in the sequence. A shortest path is a path with the shortest length over all possible paths.

We’ll illustrate on a 2D grid:

<Figure size 432x288 with 1 Axes>
<Figure size 432x288 with 1 Axes>

The nodes of this 2D grid are indexed by coordinates (i,j)(i,j).

<Figure size 432x288 with 1 Axes>

The length of the shortest path between any two nodes in a graph GG defines a metric on the vertex set (this is analagous to the geodesic metric on a manifold).

This creates an iterator over shortest path lengths for each node

Exercise

Write a function which returns a distance matrix for the shortest path length.

Spanning Trees

A tree is a connected graph with no cycles. If the graph has nn nodes, it must have m=n−1m = n-1 edges to be a tree.

A spanning tree of a graph GG is a sub-graph with the same set of nodes, and a subset of edges that forms a tree. A minimum spanning tree (MST) is a spanning tree with minimum weight (you can weight edges using a 'weight' attribute).

You can compute a spanning tree of a graph using nx.tree.minimum_spanning_tree, or nx.tree.minimum_spanning_edges. Other tree algorithms are provided as well.

<Figure size 432x288 with 1 Axes>
<Figure size 432x288 with 1 Axes>

Exercise

Create a function that generates a maze on a 2-dimensional m×nm \times n grid using nx.grid_2d_graph and a randomly weighted MST. Place the start and end points at (0,0)(0,0) and (m−1,n−1)(m-1, n-1) respectively.

Create a function that solves a maze by computing the shortest path between the start and end points.

Bipartite Graphs

A bipartite graph is a graph where nodes are separated into two sets U,VU, V, and where edges are of the form (u,v)(u,v) with u∈Uu\in U, and v∈Vv\in V (there are no edges between two points in UU or two points in VV).

Bipartite graphs are often used to encode matching problems. For example, dating websites might match romantic partners, and ride apps such as Uber and Lyft might match riders with drivers.

NetworkX functionality for biparite graphs is in nx.algorithms.bipartite

<Figure size 432x288 with 1 Axes>
NodeDataView({0: {'bipartite': 0}, 1: {'bipartite': 0}, 2: {'bipartite': 0}, 3: {'bipartite': 0}, 4: {'bipartite': 0}, 5: {'bipartite': 1}, 6: {'bipartite': 1}, 7: {'bipartite': 1}, 8: {'bipartite': 1}, 9: {'bipartite': 1}, 10: {'bipartite': 1}, 11: {'bipartite': 1}})

Let’s explicitly define positions to visualize the bipartite graph

<Figure size 432x288 with 1 Axes>
<Figure size 432x288 with 1 Axes>
{0: 5, 1: 10, 2: 6, 3: 7, 4: 8, 5: 0, 6: 2, 7: 3, 8: 4, 10: 1}
<Figure size 432x288 with 1 Axes>

Other Graph Algorithms

There are many interesting applications of graphs and many graph algorithms that you might consider using. See the NetworkX algorithms documentation to see what some of the possibilities are.

Reading Graphs

In scientific computing, you’ll typically get a graph from some sort of data. Often these graphs are referred to as “complex networks”. One good source of data is the Stanford Large Network Dataset Collection

Graphs can be stored in a variety of formats. You can find documentation for NetworkX’s read/write capabilities here.

There are also some built-in example graphs in NetworkX. One example graph is the Zachary Karate Club Graph, which encodes friendships between individuals in a Karate club. There are some other example social network graphs

<Figure size 432x288 with 1 Axes>

Here’s an example of reading and writing a graph as an edgelist: