| name | networkx |
| description | Build, analyze, and visualize networks and graphs using NetworkX (Python). Use this skill whenever the user wants to: create graphs or networks, analyze graph properties, compute centrality measures, find shortest paths, detect communities, run graph algorithms, convert graphs to/from matrices or dataframes, visualize networks with matplotlib, import/export graph files (GML, GraphML, GEXF, edgelist, etc.), work with directed or undirected graphs, weighted or multigraphs, perform social network analysis, or do any graph theory computation. Trigger on keywords: networkx, graph, network, nodes, edges, adjacency, shortest path, centrality, community detection, spanning tree, flow, clique, PageRank, bipartite, DAG, topology, graph analysis, social network. |
| allowed-tools | Bash Read Write Edit |
NetworkX Skill — Create and Manipulate Networks
NetworkX (v3.6+) is the standard Python library for graph analysis. This skill covers everything from basic graph creation to advanced algorithms. When in doubt, prefer simple explicit code over clever one-liners — graphs are complex enough on their own.
References:
- algorithms.md — Algorithm reference by category (centrality, community, flow, etc.)
- io.md — File I/O and format conversion reference
1. Choosing a Graph Class
Pick the right class first — it cannot easily be changed after construction.
import networkx as nx
G = nx.Graph()
DG = nx.DiGraph()
MG = nx.MultiGraph()
MD = nx.MultiDiGraph()
| Need | Class |
|---|
| Social networks, protein interactions | Graph |
| Web graphs, citation networks, DAGs | DiGraph |
| Transport networks (multiple routes) | MultiGraph |
| Dependency graphs with typed edges | MultiDiGraph |
Convert between types:
DG = G.to_directed()
G2 = DG.to_undirected()
2. Building Graphs
Add Nodes
Any hashable Python object is a valid node: int, str, tuple, frozenset.
G.add_node(1)
G.add_node("Alice", age=30, role="engineer")
G.add_nodes_from([2, 3, 4])
G.add_nodes_from([
("Bob", {"age": 25, "role": "designer"}),
("Carol", {"age": 35, "role": "manager"}),
])
Add Edges
G.add_edge(1, 2)
G.add_edge("Alice", "Bob", weight=0.9, relation="colleague")
G.add_edges_from([(1, 2), (2, 3), (3, 4)])
G.add_edges_from([
(1, 2, {"weight": 1.5}),
(2, 3, {"weight": 0.8}),
])
G.add_weighted_edges_from([(1, 2, 1.5), (2, 3, 0.8)])
For MultiGraph, add_edge returns the edge key (int):
k = MG.add_edge(1, 2, weight=0.5)
k = MG.add_edge(1, 2, weight=0.75)
Remove Nodes and Edges
G.remove_node(1)
G.remove_nodes_from([2, 3])
G.remove_edge(1, 2)
G.remove_edges_from([(1, 2), (2, 3)])
G.clear()
Graph-Level Attributes
G = nx.Graph(name="Social Network", created="2025")
G.graph["description"] = "Friendship graph"
3. Inspecting a Graph
G.number_of_nodes()
G.number_of_edges()
list(G.nodes)
list(G.nodes(data=True))
list(G.nodes(data="weight", default=1.0))
list(G.edges)
list(G.edges(data=True))
list(G.edges(data="weight"))
list(G.neighbors(1))
list(G.adj[1])
G.adj[1][2]["weight"]
list(DG.successors(n))
list(DG.predecessors(n))
list(DG.in_edges(n))
list(DG.out_edges(n))
G.degree(1)
dict(G.degree())
dict(G.degree(weight="weight"))
MD.in_degree(n)
MD.out_degree(n)
Node/Edge Membership
1 in G
(1, 2) in G.edges
G.has_node(1)
G.has_edge(1, 2)
4. Attributes: Read and Write
G.nodes[1]["color"]
G.nodes[1]["color"] = "red"
G[1][2]["weight"]
MG[1][2][0]["weight"]
G[1][2]["weight"] = 4.7
nx.set_node_attributes(G, {1: "red", 2: "blue"}, name="color")
nx.set_node_attributes(G, 0.0, name="score")
nx.set_edge_attributes(G, {(1,2): 1.5, (2,3): 0.8}, name="weight")
colors = nx.get_node_attributes(G, "color")
weights = nx.get_edge_attributes(G, "weight")
5. Graph Views and Subgraphs
Views are live windows — they reflect changes to the original graph without copying data.
sub = G.subgraph([1, 2, 3])
sub = G.subgraph([1, 2, 3]).copy()
esub = G.edge_subgraph([(1, 2), (2, 3)])
import networkx as nx
heavy = nx.subgraph_view(G, filter_edge=lambda u, v: G[u][v]["weight"] > 0.5)
R = DG.reverse()
R = DG.reverse(copy=True)
nx.add_path(G, [10, 11, 12, 13])
nx.add_cycle(G, [20, 21, 22])
nx.add_star(G, [0, 1, 2, 3])
6. Graph Generators
Classic
nx.complete_graph(5)
nx.complete_bipartite_graph(3, 4)
nx.cycle_graph(6)
nx.path_graph(5)
nx.star_graph(4)
nx.wheel_graph(6)
nx.petersen_graph()
nx.balanced_tree(r=3, h=2)
nx.barbell_graph(5, 2)
nx.ladder_graph(5)
nx.grid_2d_graph(4, 4)
nx.grid_graph(dim=[3, 4, 5])
nx.hypercube_graph(3)
nx.empty_graph(10)
nx.null_graph()
nx.trivial_graph()
Random
nx.erdos_renyi_graph(100, 0.15)
nx.gnm_random_graph(100, 300)
nx.barabasi_albert_graph(100, 3)
nx.watts_strogatz_graph(30, 4, 0.1)
nx.newman_watts_strogatz_graph(30, 4, 0.1)
nx.random_regular_graph(3, 20)
nx.powerlaw_cluster_graph(50, 2, 0.3)
nx.random_lobster(100, 0.9, 0.9)
nx.random_tree(10)
Social Network Datasets
nx.karate_club_graph()
nx.florentine_families_graph()
nx.les_miserables_graph()
nx.davis_southern_women_graph()
Geometric
nx.random_geometric_graph(50, 0.2)
nx.waxman_graph(50)
nx.geographical_threshold_graph(50, 100)
7. Shortest Paths
Read references/algorithms.md for the full API. Key patterns:
nx.shortest_path(G, source=1, target=5)
nx.shortest_path_length(G, source=1, target=5)
nx.has_path(G, 1, 5)
paths = nx.single_source_shortest_path(G, source=1)
lengths = nx.single_source_shortest_path_length(G, source=1)
all_paths = dict(nx.all_pairs_shortest_path(G))
all_lengths = dict(nx.all_pairs_shortest_path_length(G))
nx.dijkstra_path(G, 1, 5, weight="weight")
nx.dijkstra_path_length(G, 1, 5, weight="weight")
lengths, paths = nx.single_source_dijkstra(G, source=1, weight="weight")
nx.bellman_ford_path(G, 1, 5, weight="weight")
dist_matrix = nx.floyd_warshall_numpy(G, weight="weight")
def heuristic(a, b): return abs(a[0]-b[0]) + abs(a[1]-b[1])
nx.astar_path(G, (0,0), (3,3), heuristic=heuristic, weight="weight")
nx.average_shortest_path_length(G)
nx.average_shortest_path_length(G, weight="weight")
8. Centrality Measures
Read references/algorithms.md for all ~30 measures. Most return {node: float}.
dc = nx.degree_centrality(G)
bc = nx.betweenness_centrality(G, normalized=True, weight="weight")
ebc = nx.edge_betweenness_centrality(G, normalized=True)
cc = nx.closeness_centrality(G)
ec = nx.eigenvector_centrality(G, max_iter=1000, weight="weight")
kc = nx.katz_centrality(G, alpha=0.1, beta=1.0)
pr = nx.pagerank(DG, alpha=0.85, weight="weight")
hc = nx.harmonic_centrality(G)
top5 = sorted(bc, key=bc.get, reverse=True)[:5]
9. Community Detection
Read references/algorithms.md for all methods.
from networkx.algorithms import community
comms = community.louvain_communities(G, seed=42)
comms = community.greedy_modularity_communities(G)
gn = community.girvan_newman(G)
top_level = next(gn)
comms = community.label_propagation_communities(G)
comms = list(community.k_clique_communities(G, k=3))
mod = community.modularity(G, comms)
coverage, performance = community.partition_quality(G, comms)
node_comm = {}
for i, comm in enumerate(comms):
for node in comm:
node_comm[node] = i
10. Graph Analysis Algorithms
Connectivity
nx.is_connected(G)
nx.number_connected_components(G)
list(nx.connected_components(G))
nx.node_connectivity(G)
nx.edge_connectivity(G)
nx.is_strongly_connected(DG)
nx.is_weakly_connected(DG)
list(nx.strongly_connected_components(DG))
list(nx.weakly_connected_components(DG))
Trees and Spanning Structures
nx.is_tree(G)
nx.is_forest(G)
T = nx.minimum_spanning_tree(G, weight="weight")
T = nx.minimum_spanning_tree(G, algorithm="prim")
T = nx.maximum_spanning_tree(G, weight="weight")
list(nx.minimum_spanning_edges(G, weight="weight", data=True))
Cycles and DAGs
nx.is_directed_acyclic_graph(DG)
list(nx.topological_sort(DG))
list(nx.all_simple_cycles(DG))
list(nx.simple_cycles(DG))
nx.find_cycle(G)
nx.cycle_basis(G)
nx.ancestors(DG, node)
nx.descendants(DG, node)
nx.dag_longest_path(DG, weight="weight")
nx.transitive_closure(DG)
nx.transitive_reduction(DG)
Cliques
list(nx.find_cliques(G))
nx.graph_clique_number(G)
list(nx.cliques_containing_node(G, 1))
nx.node_clique_number(G, 1)
Flows
flow_value, flow_dict = nx.maximum_flow(G, s=0, t=5, capacity="capacity")
nx.max_flow_min_cut(G, s=0, t=5, capacity="capacity")
nx.minimum_cut(G, s=0, t=5, capacity="capacity")
nx.minimum_cut_value(G, s=0, t=5, capacity="capacity")
nx.min_cost_flow(G)
nx.min_cost_flow_cost(G)
Matching
nx.max_weight_matching(G, weight="weight")
nx.maximum_matching(G)
nx.is_perfect_matching(G, matching)
Graph Properties
nx.density(G)
nx.diameter(G)
nx.radius(G)
nx.center(G)
nx.periphery(G)
nx.eccentricity(G)
nx.average_clustering(G)
nx.transitivity(G)
nx.clustering(G)
nx.triangles(G)
nx.is_bipartite(G)
sets = nx.bipartite.sets(G)
nx.is_eulerian(G)
nx.is_planar(G)
nx.is_chordal(G)
nx.is_regular(G)
nx.is_tree(G)
Coloring
colors = nx.coloring.greedy_color(G, strategy="largest_first")
num_colors = max(colors.values()) + 1
Link Prediction
preds = nx.resource_allocation_index(G, [(1,5), (2,7)])
preds = nx.jaccard_coefficient(G, [(1,5)])
preds = nx.adamic_adar_index(G, [(1,5)])
preds = nx.preferential_attachment(G, [(1,5)])
for u, v, score in preds:
print(u, v, score)
Graph Operators
nx.compose(G1, G2)
nx.union(G1, G2)
nx.intersection(G1, G2)
nx.difference(G1, G2)
nx.complement(G)
nx.cartesian_product(G1, G2)
nx.tensor_product(G1, G2)
nx.strong_product(G1, G2)
nx.power(G, k)
Traversal
list(nx.bfs_edges(G, source=0))
list(nx.dfs_edges(G, source=0))
list(nx.bfs_tree(G, source=0).edges())
list(nx.dfs_tree(G, source=0).edges())
dict(nx.bfs_predecessors(G, source=0))
dict(nx.bfs_successors(G, source=0))
nx.bfs_layers(G, sources=[0])
11. Converting Graphs
A = nx.to_numpy_array(G, nodelist=sorted(G), weight="weight")
G2 = nx.from_numpy_array(A, create_using=nx.DiGraph)
S = nx.to_scipy_sparse_array(G, format="csr", weight="weight")
G2 = nx.from_scipy_sparse_array(S)
df = nx.to_pandas_adjacency(G, weight="weight")
G2 = nx.from_pandas_adjacency(df)
edf = nx.to_pandas_edgelist(G, source="from", target="to")
G2 = nx.from_pandas_edgelist(edf, source="from", target="to",
edge_attr=True,
create_using=nx.DiGraph)
d = nx.to_dict_of_dicts(G)
G2 = nx.from_dict_of_dicts(d)
d = nx.to_dict_of_lists(G)
G2 = nx.from_dict_of_lists(d)
edges = list(G.edges(data=True))
G2 = nx.from_edgelist([(u,v) for u,v,_ in edges])
12. File I/O
Read references/io.md for format details and options.
nx.write_graphml(G, "graph.graphml")
G = nx.read_graphml("graph.graphml")
nx.write_gml(G, "graph.gml")
G = nx.read_gml("graph.gml")
nx.write_gexf(G, "graph.gexf")
G = nx.read_gexf("graph.gexf")
nx.write_edgelist(G, "edges.txt", data=True)
G = nx.read_edgelist("edges.txt", nodetype=int, data=[("weight", float)])
nx.write_weighted_edgelist(G, "edges.txt")
G = nx.read_weighted_edgelist("edges.txt", nodetype=int)
nx.write_adjlist(G, "adj.txt")
G = nx.read_adjlist("adj.txt", nodetype=int)
nx.write_pajek(G, "graph.net")
G = nx.read_pajek("graph.net")
import json
from networkx.readwrite import json_graph
data = json_graph.node_link_data(G)
json.dump(data, open("graph.json", "w"))
G = json_graph.node_link_graph(json.load(open("graph.json")))
nx.write_network_text(G)
13. Drawing and Visualization
NetworkX's built-in drawing is for quick exploration — use Gephi or Cytoscape for publication-quality output.
Basic Drawing
import matplotlib.pyplot as plt
nx.draw(G)
nx.draw(G, with_labels=True, node_color="skyblue", node_size=500,
font_size=10, edge_color="gray")
plt.savefig("graph.png", dpi=150, bbox_inches="tight")
plt.show()
Layout Algorithms
Choose a layout, then draw with full control:
pos = nx.spring_layout(G, k=0.5, seed=42)
pos = nx.kamada_kawai_layout(G)
pos = nx.circular_layout(G)
pos = nx.shell_layout(G, nlist=[inner, outer])
pos = nx.spectral_layout(G)
pos = nx.random_layout(G, seed=42)
pos = nx.planar_layout(G)
pos = nx.bfs_layout(G, start=0)
pos = nx.spiral_layout(G)
pos = nx.bipartite_layout(G, nodes=top_nodes)
Fine-Grained Drawing
fig, ax = plt.subplots(figsize=(12, 8))
pos = nx.spring_layout(G, seed=42)
node_colors = [G.nodes[n].get("color", "lightblue") for n in G]
node_sizes = [G.degree(n) * 50 + 100 for n in G]
nx.draw_networkx_nodes(G, pos, node_color=node_colors,
node_size=node_sizes, alpha=0.8, ax=ax)
nx.draw_networkx_edges(G, pos, edge_color="gray",
width=1.5, alpha=0.6, ax=ax,
arrows=True, arrowsize=20)
nx.draw_networkx_labels(G, pos, font_size=9, ax=ax)
edge_labels = nx.get_edge_attributes(G, "weight")
nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels,
font_size=7, ax=ax)
ax.set_title("My Network")
ax.axis("off")
plt.tight_layout()
plt.savefig("network.png", dpi=150)
Color Nodes by Centrality
bc = nx.betweenness_centrality(G)
node_color = [bc[n] for n in G]
pos = nx.spring_layout(G, seed=42)
nx.draw_networkx(G, pos, node_color=node_color,
cmap=plt.cm.plasma, with_labels=True)
sm = plt.cm.ScalarMappable(cmap=plt.cm.plasma,
norm=plt.Normalize(min(bc.values()), max(bc.values())))
plt.colorbar(sm, label="Betweenness Centrality")
14. Common Patterns and Recipes
Build Graph from Pandas DataFrame
import pandas as pd
df = pd.read_csv("edges.csv")
G = nx.from_pandas_edgelist(df, source="source", target="target",
edge_attr="weight")
nodes_df = pd.read_csv("nodes.csv")
for _, row in nodes_df.iterrows():
G.nodes[row["id"]].update(row.drop("id").to_dict())
Largest Connected Component
largest_cc = max(nx.connected_components(G), key=len)
G_main = G.subgraph(largest_cc).copy()
Ego Network (Local Neighborhood)
ego = nx.ego_graph(G, node, radius=2)
Bipartite Projection
B = nx.Graph()
B.add_nodes_from(top_nodes, bipartite=0)
B.add_nodes_from(bottom_nodes, bipartite=1)
B.add_edges_from(edge_list)
from networkx.algorithms import bipartite
P = bipartite.projected_graph(B, top_nodes)
P = bipartite.weighted_projected_graph(B, top_nodes)
Weighted Graph from Co-occurrence
from itertools import combinations
G = nx.Graph()
for group in groups:
for a, b in combinations(group, 2):
if G.has_edge(a, b):
G[a][b]["weight"] += 1
else:
G.add_edge(a, b, weight=1)
Export Summary Statistics
stats = {
"nodes": G.number_of_nodes(),
"edges": G.number_of_edges(),
"density": nx.density(G),
"connected": nx.is_connected(G),
"components": nx.number_connected_components(G),
"avg_clustering": nx.average_clustering(G),
"avg_degree": sum(d for _, d in G.degree()) / G.number_of_nodes(),
}
if nx.is_connected(G):
stats["diameter"] = nx.diameter(G)
stats["avg_path_length"] = nx.average_shortest_path_length(G)
15. Performance Tips
- For large graphs (>100k nodes), prefer
nx.generators over building node-by-node.
nx.to_scipy_sparse_array() is much faster than nx.to_numpy_array() for sparse graphs.
nx.betweenness_centrality(G, k=200) uses sampling for faster approximation on big graphs.
- Use
G.subgraph(nodes) (view, no copy) instead of .copy() when read-only access is enough.
- For all-pairs operations, check if the graph is connected first — disconnected graphs return
inf distances, which crashes average_shortest_path_length.
- Set
seed= on random generators and layout algorithms for reproducibility.
nx.is_directed(), nx.is_weighted(), nx.is_empty() are fast graph-property checks.
Installation
pip install networkx
pip install networkx[default]
pip install networkx[extra]
Import convention:
import networkx as nx
from networkx.algorithms import community
from networkx.algorithms import bipartite