Online NetworkX Compiler

Run NetworkX code in your browser. Build graphs, find shortest paths, rank nodes by centrality, find communities and draw them.

Python
# Source:
# https://networkx.org/documentation/stable/auto_examples/drawing/plot_weighted_graph.html#sphx-glr-auto-examples-drawing-plot-weighted-graph-py
import matplotlib.pyplot as plt
import networkx as nx

G = nx.Graph()

G.add_edge("a", "b", weight=0.6)
G.add_edge("a", "c", weight=0.2)
G.add_edge("c", "d", weight=0.1)
G.add_edge("c", "e", weight=0.7)
G.add_edge("c", "f", weight=0.9)
G.add_edge("a", "d", weight=0.3)

elarge = [(u, v) for (u, v, d) in G.edges(data=True) if d["weight"] > 0.5]
esmall = [(u, v) for (u, v, d) in G.edges(data=True) if d["weight"] <= 0.5]

pos = nx.spring_layout(G, seed=7)  # positions for all nodes - seed for reproducibility

# nodes
nx.draw_networkx_nodes(G, pos, node_size=700)

# edges
nx.draw_networkx_edges(G, pos, edgelist=elarge, width=6)
nx.draw_networkx_edges(
    G, pos, edgelist=esmall, width=6, alpha=0.5, edge_color="b", style="dashed"
)

# node labels
nx.draw_networkx_labels(G, pos, font_size=20, font_family="sans-serif")
# edge weight labels
edge_labels = nx.get_edge_attributes(G, "weight")
nx.draw_networkx_edge_labels(G, pos, edge_labels)

ax = plt.gca()
ax.margins(0.08)
plt.axis("off")
plt.tight_layout()
plt.show()

NetworkX is a pure-Python library for graphs: sets of nodes joined by edges. A node can be any hashable Python object, such as a string, a number or a tuple, and nodes and edges can carry attributes such as a weight. NetworkX has algorithms for shortest paths, centrality, connected components and communities, and it draws graphs with matplotlib. People use it to study social networks, road maps and dependency graphs. This page is an online NetworkX compiler: the code runs in your browser, so you can try it without installing anything. Run the example first, then paste any snippet below into a new cell to try it.

What the example does

nx.Graph() creates an empty undirected graph. G.add_edge() adds both nodes if they are new, so the six calls give six nodes, a to f, and six edges, each with a weight attribute. G.edges(data=True) yields every edge with its attributes, and the two list comprehensions split the edges at 0.5: three heavy and three light. nx.spring_layout(G, seed=7) places the nodes with a force-directed algorithm, in which edges pull nodes together and all nodes push each other apart. The seed gives the same layout on every run. The draw_networkx_* functions then draw onto a matplotlib figure: the nodes, heavy edges as solid lines, light edges dashed and half transparent, the node names, and the weights that nx.get_edge_attributes(G, "weight") collects into a dictionary.

Find the shortest path

nx.shortest_path() counts edges unless you pass weight, so the first two calls disagree. The road from Home to School is one edge but 10 km long, while the route through the Park is 3.5 km:

import networkx as nx

roads = nx.Graph()
roads.add_weighted_edges_from([          # (from, to, distance in km)
    ("Home", "School", 10.0),
    ("Home", "Park", 2.0), ("Park", "School", 1.5),
    ("Park", "Mall", 3.0), ("Mall", "School", 1.0),
])

print(nx.shortest_path(roads, "Home", "School"))                     # fewest edges
print(nx.shortest_path(roads, "Home", "School", weight="weight"))    # shortest distance
print(nx.shortest_path_length(roads, "Home", "School", weight="weight"))
print(nx.single_source_dijkstra_path_length(roads, "Home"))          # distance to every node

Find the most central nodes

nx.karate_club_graph() ships with NetworkX: Zachary's karate club, 34 members and the 78 ties between them. Degree counts a node's neighbours. Betweenness is the share of shortest paths between other nodes that pass through a node, so it picks out the go-betweens:

import networkx as nx

G = nx.karate_club_graph()
print(G.number_of_nodes(), "nodes,", G.number_of_edges(), "edges")

degree = dict(G.degree())
betweenness = nx.betweenness_centrality(G)
top = sorted(betweenness, key=betweenness.get, reverse=True)[:3]
for node in top:
    print(f"node {node}: {degree[node]} ties, betweenness {betweenness[node]:.3f}")

print("connected:", nx.is_connected(G), "density:", round(nx.density(G), 3))

Order tasks with a directed graph

In a nx.DiGraph, every edge has a direction. Here an edge points from a task to a task that needs it. nx.topological_sort() lists the tasks in an order that respects every edge, and raises NetworkXUnfeasible if the graph has a cycle:

import networkx as nx

tasks = nx.DiGraph()
tasks.add_edges_from([
    ("download data", "clean data"),
    ("clean data", "train model"),
    ("clean data", "make charts"),
    ("train model", "write report"),
    ("make charts", "write report"),
])

print(nx.is_directed_acyclic_graph(tasks))
print(list(nx.topological_sort(tasks)))
print(list(tasks.predecessors("write report")))
print(sorted(nx.ancestors(tasks, "train model")))

Find communities and draw them

louvain_communities() splits a graph into groups with many edges inside and few between them. It is randomized, so pass a seed to get the same groups every time. nx.draw() then colours each node by its group:

import matplotlib.pyplot as plt
import networkx as nx

G = nx.karate_club_graph()
groups = nx.community.louvain_communities(G, seed=42)
print(len(groups), "communities, sizes", [len(g) for g in groups])
print("modularity", round(nx.community.modularity(G, groups), 3))

group_of = {node: i for i, group in enumerate(groups) for node in group}
pos = nx.spring_layout(G, seed=3)
nx.draw(G, pos, node_color=[group_of[n] for n in G], cmap=plt.cm.tab10,
        with_labels=True, node_size=300, font_size=8, edge_color="gray")
plt.show()

Good to know

  • A Graph keeps one edge per pair of nodes. Adding the same edge again only updates its attributes. Use nx.MultiGraph for parallel edges.
  • nx.from_pandas_edgelist(df, "source", "target", edge_attr="weight") builds a graph from a pandas table of edges.
  • Pure Python is slow on large graphs. On a random graph with 2,000 nodes and 8,000 edges, betweenness_centrality() took about 30 times as long as the same calculation in igraph.