Skill Tracer
Skills › Scientific Agent Skills › networkx › visualization.md

visualization.md

545 lines · skills/networkx/references/visualization.md at 5f2bc03

Open on GitHub
1# NetworkX Graph Visualization
2
3API patterns assume suitable graphs and imports; examples use simple graphs unless stated. Geometric layout distance is not an observed physical or statistical distance. See [review.md](review.md) for executed rendering checks and optional integration limits.
4

NetworkX Graph Visualization

API patterns assume suitable graphs and imports; examples use simple graphs unless stated. Geometric layout distance is not an observed physical or statistical distance. See review.md for executed rendering checks and optional integration limits.

Raw lines 1 to 4
5## Basic Drawing with Matplotlib
6

Basic Drawing with Matplotlib

Raw lines 5 to 6
7### Simple Visualization
8```python
9import networkx as nx
10import matplotlib.pyplot as plt
12# Create and draw graph
13G = nx.karate_club_graph()
14nx.draw(G)
15plt.show()
17# Save to file
18nx.draw(G)
19plt.savefig('graph.png', dpi=300, bbox_inches='tight')
20plt.close()
21```
23NetworkX 3.5 added `nx.display(G)`, a newer declarative drawing API that reads visualization attributes (color, size, position) stored directly on nodes and edges. `nx.draw` and the `draw_networkx_*` functions below remain fully supported.

Simple Visualization

import networkx as nx
import matplotlib.pyplot as plt

# Create and draw graph
G = nx.karate_club_graph()
nx.draw(G)
plt.show()

# Save to file
nx.draw(G)
plt.savefig('graph.png', dpi=300, bbox_inches='tight')
plt.close()

NetworkX 3.5 added nx.display(G), a newer declarative drawing API that reads visualization attributes (color, size, position) stored directly on nodes and edges. nx.draw and the draw_networkx_* functions below remain fully supported.

Raw lines 7 to 24
25### Drawing with Labels
26```python
27# Draw with node labels
28nx.draw(G, with_labels=True)
29plt.show()
31# Custom labels
32labels = {i: f"Node {i}" for i in G.nodes()}
33nx.draw(G, labels=labels, with_labels=True)
34plt.show()
35```

Drawing with Labels

# Draw with node labels
nx.draw(G, with_labels=True)
plt.show()

# Custom labels
labels = {i: f"Node {i}" for i in G.nodes()}
nx.draw(G, labels=labels, with_labels=True)
plt.show()
Raw lines 25 to 36
37## Layout Algorithms

Layout Algorithms

Raw lines 37 to 38
39### Spring Layout (Force-Directed)
40```python
41# Fruchterman-Reingold force-directed algorithm
42pos = nx.spring_layout(G, seed=42)
43nx.draw(G, pos=pos, with_labels=True)
44plt.show()
46# With parameters
47pos = nx.spring_layout(G, k=0.5, iterations=50, seed=42)
48```
50`spring_layout(method="auto")` uses force below 500 nodes and energy otherwise. Energy uses absolute edge weights and component gravity; force can behave differently on signed graphs. Set `method`, `weight` and `seed` when comparing layouts. Large weights attract nodes more strongly, unlike shortest-path costs.

Spring Layout (Force-Directed)

# Fruchterman-Reingold force-directed algorithm
pos = nx.spring_layout(G, seed=42)
nx.draw(G, pos=pos, with_labels=True)
plt.show()

# With parameters
pos = nx.spring_layout(G, k=0.5, iterations=50, seed=42)

spring_layout(method="auto") uses force below 500 nodes and energy otherwise. Energy uses absolute edge weights and component gravity; force can behave differently on signed graphs. Set method, weight and seed when comparing layouts. Large weights attract nodes more strongly, unlike shortest-path costs.

Raw lines 39 to 51
52### Circular Layout
53```python
54# Arrange nodes in circle
55pos = nx.circular_layout(G)
56nx.draw(G, pos=pos, with_labels=True)
57plt.show()
58```

Circular Layout

# Arrange nodes in circle
pos = nx.circular_layout(G)
nx.draw(G, pos=pos, with_labels=True)
plt.show()
Raw lines 52 to 59
60### Random Layout
61```python
62# Random positioning
63pos = nx.random_layout(G, seed=42)
64nx.draw(G, pos=pos, with_labels=True)
65plt.show()
66```

Random Layout

# Random positioning
pos = nx.random_layout(G, seed=42)
nx.draw(G, pos=pos, with_labels=True)
plt.show()
Raw lines 60 to 67
68### Shell Layout
69```python
70# Concentric circles
71pos = nx.shell_layout(G)
72nx.draw(G, pos=pos, with_labels=True)
73plt.show()
75# With custom shells
76shells = [[0, 1, 2], [3, 4, 5, 6], [7, 8, 9]]
77pos = nx.shell_layout(G, nlist=shells)
78```

Shell Layout

# Concentric circles
pos = nx.shell_layout(G)
nx.draw(G, pos=pos, with_labels=True)
plt.show()

# With custom shells
shells = [[0, 1, 2], [3, 4, 5, 6], [7, 8, 9]]
pos = nx.shell_layout(G, nlist=shells)
Raw lines 68 to 79
80### Spectral Layout
81```python
82# Use eigenvectors of graph Laplacian
83pos = nx.spectral_layout(G)
84nx.draw(G, pos=pos, with_labels=True)
85plt.show()
86```

Spectral Layout

# Use eigenvectors of graph Laplacian
pos = nx.spectral_layout(G)
nx.draw(G, pos=pos, with_labels=True)
plt.show()
Raw lines 80 to 87
88### Kamada-Kawai Layout
89```python
90# Energy-based layout
91pos = nx.kamada_kawai_layout(G)
92nx.draw(G, pos=pos, with_labels=True)
93plt.show()
94```

Kamada-Kawai Layout

# Energy-based layout
pos = nx.kamada_kawai_layout(G)
nx.draw(G, pos=pos, with_labels=True)
plt.show()
Raw lines 88 to 95
96### Planar Layout
97```python
98# For planar graphs only
99if nx.is_planar(G):
100 pos = nx.planar_layout(G)
101 nx.draw(G, pos=pos, with_labels=True)
102 plt.show()
103```

Planar Layout

# For planar graphs only
if nx.is_planar(G):
    pos = nx.planar_layout(G)
    nx.draw(G, pos=pos, with_labels=True)
    plt.show()
Raw lines 96 to 104
105### Tree Layouts
106```python
107# For tree graphs
108if nx.is_tree(G):
109 # Requires pygraphviz (verify its Graphviz runtime availability)
110 pos = nx.nx_agraph.graphviz_layout(G, prog='dot')
111 nx.draw(G, pos=pos, with_labels=True)
112 plt.show()
113```

Tree Layouts

# For tree graphs
if nx.is_tree(G):
    # Requires pygraphviz (verify its Graphviz runtime availability)
    pos = nx.nx_agraph.graphviz_layout(G, prog='dot')
    nx.draw(G, pos=pos, with_labels=True)
    plt.show()
Raw lines 105 to 114
115## Customizing Node Appearance

Customizing Node Appearance

Raw lines 115 to 116
117### Node Colors
118```python
119# Single color
120nx.draw(G, node_color='red')
122# Different colors per node
123node_colors = ['red' if G.degree(n) > 5 else 'blue' for n in G.nodes()]
124nx.draw(G, node_color=node_colors)
126# Color by attribute
127pos = nx.spring_layout(G, seed=42)
128colors = [G.degree(n) for n in G]
129fig, ax = plt.subplots()
130nx.draw_networkx_edges(G, pos, ax=ax)
131artist = nx.draw_networkx_nodes(G, pos, node_color=colors, cmap="viridis", ax=ax)
132fig.colorbar(artist, ax=ax, label="Degree")
133plt.show()
134```

Node Colors

# Single color
nx.draw(G, node_color='red')

# Different colors per node
node_colors = ['red' if G.degree(n) > 5 else 'blue' for n in G.nodes()]
nx.draw(G, node_color=node_colors)

# Color by attribute
pos = nx.spring_layout(G, seed=42)
colors = [G.degree(n) for n in G]
fig, ax = plt.subplots()
nx.draw_networkx_edges(G, pos, ax=ax)
artist = nx.draw_networkx_nodes(G, pos, node_color=colors, cmap="viridis", ax=ax)
fig.colorbar(artist, ax=ax, label="Degree")
plt.show()
Raw lines 117 to 135
136### Node Sizes
137```python
138# Size by degree
139node_sizes = [100 * G.degree(n) for n in G.nodes()]
140nx.draw(G, node_size=node_sizes)
142# Size by centrality
143centrality = nx.degree_centrality(G)
144node_sizes = [3000 * centrality[n] for n in G.nodes()]
145nx.draw(G, node_size=node_sizes)
146```

Node Sizes

# Size by degree
node_sizes = [100 * G.degree(n) for n in G.nodes()]
nx.draw(G, node_size=node_sizes)

# Size by centrality
centrality = nx.degree_centrality(G)
node_sizes = [3000 * centrality[n] for n in G.nodes()]
nx.draw(G, node_size=node_sizes)
Raw lines 136 to 147
148### Node Shapes
149```python
150# Draw nodes separately with different shapes
151pos = nx.spring_layout(G)
153# Circle nodes
154nx.draw_networkx_nodes(G, pos, nodelist=[0, 1, 2],
155 node_shape='o', node_color='red')
157# Square nodes
158nx.draw_networkx_nodes(G, pos, nodelist=[3, 4, 5],
159 node_shape='s', node_color='blue')
161nx.draw_networkx_edges(G, pos)
162nx.draw_networkx_labels(G, pos)
163plt.show()
164```

Node Shapes

# Draw nodes separately with different shapes
pos = nx.spring_layout(G)

# Circle nodes
nx.draw_networkx_nodes(G, pos, nodelist=[0, 1, 2],
                       node_shape='o', node_color='red')

# Square nodes
nx.draw_networkx_nodes(G, pos, nodelist=[3, 4, 5],
                       node_shape='s', node_color='blue')

nx.draw_networkx_edges(G, pos)
nx.draw_networkx_labels(G, pos)
plt.show()
Raw lines 148 to 165
166### Node Borders
167```python
168nx.draw(G, pos=pos,
169 node_color='lightblue',
170 edgecolors='black', # Node border color
171 linewidths=2) # Node border width
172plt.show()
173```

Node Borders

nx.draw(G, pos=pos,
        node_color='lightblue',
        edgecolors='black',  # Node border color
        linewidths=2)        # Node border width
plt.show()
Raw lines 166 to 174
175## Customizing Edge Appearance

Customizing Edge Appearance

Raw lines 175 to 176
177### Edge Colors
178```python
179# Single color
180nx.draw(G, edge_color='gray')
182# Different colors per edge
183edge_colors = ['red' if G[u][v].get('weight', 1) > 0.5 else 'blue'
184 for u, v in G.edges()]
185nx.draw(G, edge_color=edge_colors)
187# Color by weight
188edges = G.edges()
189weights = [G[u][v].get('weight', 1) for u, v in edges]
190nx.draw(G, edge_color=weights, edge_cmap=plt.cm.Reds)
191```

Edge Colors

# Single color
nx.draw(G, edge_color='gray')

# Different colors per edge
edge_colors = ['red' if G[u][v].get('weight', 1) > 0.5 else 'blue'
               for u, v in G.edges()]
nx.draw(G, edge_color=edge_colors)

# Color by weight
edges = G.edges()
weights = [G[u][v].get('weight', 1) for u, v in edges]
nx.draw(G, edge_color=weights, edge_cmap=plt.cm.Reds)
Raw lines 177 to 192
193### Edge Widths
194```python
195# Width by weight
196edge_widths = [3 * G[u][v].get('weight', 1) for u, v in G.edges()]
197nx.draw(G, width=edge_widths)
199# Width by betweenness
200edge_betweenness = nx.edge_betweenness_centrality(G)
201edge_widths = [5 * edge_betweenness[(u, v)] for u, v in G.edges()]
202nx.draw(G, width=edge_widths)
203```

Edge Widths

# Width by weight
edge_widths = [3 * G[u][v].get('weight', 1) for u, v in G.edges()]
nx.draw(G, width=edge_widths)

# Width by betweenness
edge_betweenness = nx.edge_betweenness_centrality(G)
edge_widths = [5 * edge_betweenness[(u, v)] for u, v in G.edges()]
nx.draw(G, width=edge_widths)
Raw lines 193 to 204
205### Edge Styles
206```python
207# Dashed edges
208nx.draw(G, style='dashed')
210# Different styles per edge
211pos = nx.spring_layout(G)
212strong_edges = [(u, v) for u, v in G.edges() if G[u][v].get('weight', 0) > 0.5]
213weak_edges = [(u, v) for u, v in G.edges() if G[u][v].get('weight', 0) <= 0.5]
215nx.draw_networkx_nodes(G, pos)
216nx.draw_networkx_edges(G, pos, edgelist=strong_edges, style='solid', width=2)
217nx.draw_networkx_edges(G, pos, edgelist=weak_edges, style='dashed', width=1)
218plt.show()
219```

Edge Styles

# Dashed edges
nx.draw(G, style='dashed')

# Different styles per edge
pos = nx.spring_layout(G)
strong_edges = [(u, v) for u, v in G.edges() if G[u][v].get('weight', 0) > 0.5]
weak_edges = [(u, v) for u, v in G.edges() if G[u][v].get('weight', 0) <= 0.5]

nx.draw_networkx_nodes(G, pos)
nx.draw_networkx_edges(G, pos, edgelist=strong_edges, style='solid', width=2)
nx.draw_networkx_edges(G, pos, edgelist=weak_edges, style='dashed', width=1)
plt.show()
Raw lines 205 to 220
221### Directed Graphs (Arrows)
222```python
223# Draw directed graph with arrows
224G_directed = nx.DiGraph([(1, 2), (2, 3), (3, 1)])
225pos = nx.spring_layout(G_directed)
227nx.draw(G_directed, pos=pos, with_labels=True,
228 arrows=True,
229 arrowsize=20,
230 arrowstyle='->',
231 connectionstyle='arc3,rad=0.1')
232plt.show()
233```

Directed Graphs (Arrows)

# Draw directed graph with arrows
G_directed = nx.DiGraph([(1, 2), (2, 3), (3, 1)])
pos = nx.spring_layout(G_directed)

nx.draw(G_directed, pos=pos, with_labels=True,
        arrows=True,
        arrowsize=20,
        arrowstyle='->',
        connectionstyle='arc3,rad=0.1')
plt.show()
Raw lines 221 to 234
235## Labels and Annotations

Labels and Annotations

Raw lines 235 to 236
237### Node Labels
238```python
239pos = nx.spring_layout(G)
241# Custom labels
242labels = {n: f"N{n}" for n in G.nodes()}
243nx.draw_networkx_labels(G, pos, labels=labels, font_size=12, font_color='white')
245# Font customization
246nx.draw_networkx_labels(G, pos,
247 font_size=10,
248 font_family='serif',
249 font_weight='bold')
250```

Node Labels

pos = nx.spring_layout(G)

# Custom labels
labels = {n: f"N{n}" for n in G.nodes()}
nx.draw_networkx_labels(G, pos, labels=labels, font_size=12, font_color='white')

# Font customization
nx.draw_networkx_labels(G, pos,
                       font_size=10,
                       font_family='serif',
                       font_weight='bold')
Raw lines 237 to 251
252### Edge Labels
253```python
254pos = nx.spring_layout(G)
255nx.draw_networkx_nodes(G, pos)
256nx.draw_networkx_edges(G, pos)
258# Edge labels from attributes
259edge_labels = nx.get_edge_attributes(G, 'weight')
260nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels)
261plt.show()
263# Custom edge labels
264edge_labels = {(u, v): f"{u}-{v}" for u, v in G.edges()}
265nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels)
266```

Edge Labels

pos = nx.spring_layout(G)
nx.draw_networkx_nodes(G, pos)
nx.draw_networkx_edges(G, pos)

# Edge labels from attributes
edge_labels = nx.get_edge_attributes(G, 'weight')
nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels)
plt.show()

# Custom edge labels
edge_labels = {(u, v): f"{u}-{v}" for u, v in G.edges()}
nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels)
Raw lines 252 to 267
268## Advanced Drawing Techniques

Advanced Drawing Techniques

Raw lines 268 to 269
270### Combining Draw Functions
271```python
272# Full control by separating components
273pos = nx.spring_layout(G, seed=42)
275# Draw edges
276nx.draw_networkx_edges(G, pos, alpha=0.3, width=1)
278# Draw nodes
279nx.draw_networkx_nodes(G, pos,
280 node_color='lightblue',
281 node_size=500,
282 edgecolors='black')
284# Draw labels
285nx.draw_networkx_labels(G, pos, font_size=10)
287# Remove axis
288plt.axis('off')
289plt.tight_layout()
290plt.show()
291```

Combining Draw Functions

# Full control by separating components
pos = nx.spring_layout(G, seed=42)

# Draw edges
nx.draw_networkx_edges(G, pos, alpha=0.3, width=1)

# Draw nodes
nx.draw_networkx_nodes(G, pos,
                       node_color='lightblue',
                       node_size=500,
                       edgecolors='black')

# Draw labels
nx.draw_networkx_labels(G, pos, font_size=10)

# Remove axis
plt.axis('off')
plt.tight_layout()
plt.show()
Raw lines 270 to 292
293### Subgraph Highlighting
294```python
295pos = nx.spring_layout(G)
297# Identify subgraph to highlight
298subgraph_nodes = [1, 2, 3, 4]
299subgraph = G.subgraph(subgraph_nodes)
301# Draw main graph
302nx.draw_networkx_nodes(G, pos, node_color='lightgray', node_size=300)
303nx.draw_networkx_edges(G, pos, alpha=0.2)
305# Highlight subgraph
306nx.draw_networkx_nodes(subgraph, pos, node_color='red', node_size=500)
307nx.draw_networkx_edges(subgraph, pos, edge_color='red', width=2)
309nx.draw_networkx_labels(G, pos)
310plt.axis('off')
311plt.show()
312```

Subgraph Highlighting

pos = nx.spring_layout(G)

# Identify subgraph to highlight
subgraph_nodes = [1, 2, 3, 4]
subgraph = G.subgraph(subgraph_nodes)

# Draw main graph
nx.draw_networkx_nodes(G, pos, node_color='lightgray', node_size=300)
nx.draw_networkx_edges(G, pos, alpha=0.2)

# Highlight subgraph
nx.draw_networkx_nodes(subgraph, pos, node_color='red', node_size=500)
nx.draw_networkx_edges(subgraph, pos, edge_color='red', width=2)

nx.draw_networkx_labels(G, pos)
plt.axis('off')
plt.show()
Raw lines 293 to 313
314### Community Coloring
315```python
316from networkx.algorithms import community
318# Detect communities
319communities = community.greedy_modularity_communities(G)
321# Assign colors
322color_map = {}
323colors = ['red', 'blue', 'green', 'yellow', 'purple', 'orange']
324for i, comm in enumerate(communities):
325 for node in comm:
326 color_map[node] = colors[i % len(colors)]
328node_colors = [color_map[n] for n in G.nodes()]
330pos = nx.spring_layout(G)
331nx.draw(G, pos=pos, node_color=node_colors, with_labels=True)
332plt.show()
333```

Community Coloring

from networkx.algorithms import community

# Detect communities
communities = community.greedy_modularity_communities(G)

# Assign colors
color_map = {}
colors = ['red', 'blue', 'green', 'yellow', 'purple', 'orange']
for i, comm in enumerate(communities):
    for node in comm:
        color_map[node] = colors[i % len(colors)]

node_colors = [color_map[n] for n in G.nodes()]

pos = nx.spring_layout(G)
nx.draw(G, pos=pos, node_color=node_colors, with_labels=True)
plt.show()
Raw lines 314 to 334
335## Creating Publication-Quality Figures

Creating Publication-Quality Figures

Raw lines 335 to 336
337### High Resolution Export
338```python
339fig, ax = plt.subplots(figsize=(12, 8))
340pos = nx.spring_layout(G, seed=42)
342nx.draw(G, pos=pos, ax=ax,
343 node_color='lightblue',
344 node_size=500,
345 edge_color='gray',
346 width=1,
347 with_labels=True,
348 font_size=10)
350plt.title('Graph Visualization', fontsize=16)
351plt.axis('off')
352plt.tight_layout()
353plt.savefig('publication_graph.png', dpi=300, bbox_inches='tight')
354plt.savefig('publication_graph.pdf', bbox_inches='tight') # Vector format
355plt.close()
356```

High Resolution Export

fig, ax = plt.subplots(figsize=(12, 8))
pos = nx.spring_layout(G, seed=42)

nx.draw(G, pos=pos, ax=ax,
        node_color='lightblue',
        node_size=500,
        edge_color='gray',
        width=1,
        with_labels=True,
        font_size=10)

plt.title('Graph Visualization', fontsize=16)
plt.axis('off')
plt.tight_layout()
plt.savefig('publication_graph.png', dpi=300, bbox_inches='tight')
plt.savefig('publication_graph.pdf', bbox_inches='tight')  # Vector format
plt.close()
Raw lines 337 to 357
358### Multi-Panel Figures
359```python
360fig, axes = plt.subplots(1, 3, figsize=(18, 6))
362# Different layouts
363layouts = [nx.circular_layout(G), nx.spring_layout(G), nx.spectral_layout(G)]
364titles = ['Circular', 'Spring', 'Spectral']
366for ax, pos, title in zip(axes, layouts, titles):
367 nx.draw(G, pos=pos, ax=ax, with_labels=True, node_color='lightblue')
368 ax.set_title(title)
369 ax.axis('off')
371plt.tight_layout()
372plt.savefig('layouts_comparison.png', dpi=300)
373plt.close()
374```

Multi-Panel Figures

fig, axes = plt.subplots(1, 3, figsize=(18, 6))

# Different layouts
layouts = [nx.circular_layout(G), nx.spring_layout(G), nx.spectral_layout(G)]
titles = ['Circular', 'Spring', 'Spectral']

for ax, pos, title in zip(axes, layouts, titles):
    nx.draw(G, pos=pos, ax=ax, with_labels=True, node_color='lightblue')
    ax.set_title(title)
    ax.axis('off')

plt.tight_layout()
plt.savefig('layouts_comparison.png', dpi=300)
plt.close()
Raw lines 358 to 375
376## Interactive Visualization Libraries

Interactive Visualization Libraries

Raw lines 376 to 377
378### Plotly (Interactive)
379```python
380import plotly.graph_objects as go
382# Create positions
383pos = nx.spring_layout(G)
385# Edge trace
386edge_x = []
387edge_y = []
388for edge in G.edges():
389 x0, y0 = pos[edge[0]]
390 x1, y1 = pos[edge[1]]
391 edge_x.extend([x0, x1, None])
392 edge_y.extend([y0, y1, None])
394edge_trace = go.Scatter(
395 x=edge_x, y=edge_y,
396 line=dict(width=0.5, color='#888'),
397 hoverinfo='none',
398 mode='lines')
400# Node trace
401node_x = [pos[node][0] for node in G.nodes()]
402node_y = [pos[node][1] for node in G.nodes()]
404node_trace = go.Scatter(
405 x=node_x, y=node_y,
406 mode='markers',
407 hoverinfo='text',
408 marker=dict(
409 showscale=True,
410 colorscale='YlGnBu',
411 size=10,
412 colorbar=dict(thickness=15, title=dict(text='Node Connections')),
413 line_width=2))
415# Color by degree
416node_adjacencies = [len(list(G.neighbors(node))) for node in G.nodes()]
417node_trace.marker.color = node_adjacencies
418node_trace.text = [f"{node}: degree {degree}" for node, degree in zip(G, node_adjacencies)]
420fig = go.Figure(data=[edge_trace, node_trace],
421 layout=go.Layout(
422 showlegend=False,
423 hovermode='closest',
424 margin=dict(b=0, l=0, r=0, t=0)))
426fig.show()
427```

Plotly (Interactive)

import plotly.graph_objects as go

# Create positions
pos = nx.spring_layout(G)

# Edge trace
edge_x = []
edge_y = []
for edge in G.edges():
    x0, y0 = pos[edge[0]]
    x1, y1 = pos[edge[1]]
    edge_x.extend([x0, x1, None])
    edge_y.extend([y0, y1, None])

edge_trace = go.Scatter(
    x=edge_x, y=edge_y,
    line=dict(width=0.5, color='#888'),
    hoverinfo='none',
    mode='lines')

# Node trace
node_x = [pos[node][0] for node in G.nodes()]
node_y = [pos[node][1] for node in G.nodes()]

node_trace = go.Scatter(
    x=node_x, y=node_y,
    mode='markers',
    hoverinfo='text',
    marker=dict(
        showscale=True,
        colorscale='YlGnBu',
        size=10,
        colorbar=dict(thickness=15, title=dict(text='Node Connections')),
        line_width=2))

# Color by degree
node_adjacencies = [len(list(G.neighbors(node))) for node in G.nodes()]
node_trace.marker.color = node_adjacencies
node_trace.text = [f"{node}: degree {degree}" for node, degree in zip(G, node_adjacencies)]

fig = go.Figure(data=[edge_trace, node_trace],
                layout=go.Layout(
                    showlegend=False,
                    hovermode='closest',
                    margin=dict(b=0, l=0, r=0, t=0)))

fig.show()
Raw lines 378 to 428
429### PyVis (Interactive HTML)
430```python
431from pyvis.network import Network
433# Create network
434net = Network(notebook=False, height="750px", width="100%", directed=G.is_directed(),
435 cdn_resources="in_line")
437# Add nodes and edges from NetworkX
438# pyvis can modify passed attribute dicts; copy input first
439from copy import deepcopy
440net.from_nx(deepcopy(G))
442# Customize
443net.show_buttons(filter_=['physics'])
445# Save
446net.write_html("graph.html", notebook=False, open_browser=False)
447```
449PyVis accepts integer/string IDs and does not faithfully represent keyed parallel edges; prepare an explicit simple-graph projection or edge-table visualization. This standalone export bundles resources and does not open a browser. Treat HTML labels/tooltips as markup and sanitize user-supplied content. Plotly's line-trace recipe above has no arrowheads, so it is illustrative for undirected topology.

PyVis (Interactive HTML)

from pyvis.network import Network

# Create network
net = Network(notebook=False, height="750px", width="100%", directed=G.is_directed(),
              cdn_resources="in_line")

# Add nodes and edges from NetworkX
# pyvis can modify passed attribute dicts; copy input first
from copy import deepcopy
net.from_nx(deepcopy(G))

# Customize
net.show_buttons(filter_=['physics'])

# Save
net.write_html("graph.html", notebook=False, open_browser=False)

PyVis accepts integer/string IDs and does not faithfully represent keyed parallel edges; prepare an explicit simple-graph projection or edge-table visualization. This standalone export bundles resources and does not open a browser. Treat HTML labels/tooltips as markup and sanitize user-supplied content. Plotly's line-trace recipe above has no arrowheads, so it is illustrative for undirected topology.

Raw lines 429 to 450
451### Graphviz (via pydot)
452```python
453# Requires graphviz and pydot
454from networkx.drawing.nx_pydot import graphviz_layout
456pos = graphviz_layout(G, prog='neato') # neato, dot, fdp, sfdp, circo, twopi
457nx.draw(G, pos=pos, with_labels=True)
458plt.show()
460# Export to graphviz
461nx.drawing.nx_pydot.write_dot(G, 'graph.dot')
462```

Graphviz (via pydot)

# Requires graphviz and pydot
from networkx.drawing.nx_pydot import graphviz_layout

pos = graphviz_layout(G, prog='neato')  # neato, dot, fdp, sfdp, circo, twopi
nx.draw(G, pos=pos, with_labels=True)
plt.show()

# Export to graphviz
nx.drawing.nx_pydot.write_dot(G, 'graph.dot')
Raw lines 451 to 463
464## Bipartite Graph Visualization

Bipartite Graph Visualization

Raw lines 464 to 465
466### Two-Set Layout
467```python
468from networkx.algorithms import bipartite
470# Create bipartite graph
471B = nx.Graph()
472B.add_nodes_from([1, 2, 3, 4], bipartite=0)
473B.add_nodes_from(['a', 'b', 'c', 'd', 'e'], bipartite=1)
474B.add_edges_from([(1, 'a'), (1, 'b'), (2, 'b'), (2, 'c'), (3, 'd'), (4, 'e')])
476# Layout with two columns
477pos = {}
478top_nodes = [n for n, d in B.nodes(data=True) if d['bipartite'] == 0]
479bottom_nodes = [n for n, d in B.nodes(data=True) if d['bipartite'] == 1]
481pos.update({node: (0, i) for i, node in enumerate(top_nodes)})
482pos.update({node: (1, i) for i, node in enumerate(bottom_nodes)})
484nx.draw(B, pos=pos, with_labels=True,
485 node_color=['lightblue' if B.nodes[n]['bipartite'] == 0 else 'lightgreen'
486 for n in B.nodes()])
487plt.show()
488```

Two-Set Layout

from networkx.algorithms import bipartite

# Create bipartite graph
B = nx.Graph()
B.add_nodes_from([1, 2, 3, 4], bipartite=0)
B.add_nodes_from(['a', 'b', 'c', 'd', 'e'], bipartite=1)
B.add_edges_from([(1, 'a'), (1, 'b'), (2, 'b'), (2, 'c'), (3, 'd'), (4, 'e')])

# Layout with two columns
pos = {}
top_nodes = [n for n, d in B.nodes(data=True) if d['bipartite'] == 0]
bottom_nodes = [n for n, d in B.nodes(data=True) if d['bipartite'] == 1]

pos.update({node: (0, i) for i, node in enumerate(top_nodes)})
pos.update({node: (1, i) for i, node in enumerate(bottom_nodes)})

nx.draw(B, pos=pos, with_labels=True,
        node_color=['lightblue' if B.nodes[n]['bipartite'] == 0 else 'lightgreen'
                   for n in B.nodes()])
plt.show()
Raw lines 466 to 489
490## 3D Visualization

3D Visualization

Raw lines 490 to 491
492### 3D Network Plot
493```python
494import matplotlib.pyplot as plt
495import numpy as np
497# 3D spring layout
498pos = nx.spring_layout(G, dim=3, seed=42)
500# Extract coordinates
501node_xyz = np.array([pos[v] for v in G.nodes()])
502edge_xyz = np.array([(pos[u], pos[v]) for u, v in G.edges()])
504# Create figure
505fig = plt.figure(figsize=(10, 8))
506ax = fig.add_subplot(111, projection='3d')
508# Plot edges
509for vizedge in edge_xyz:
510 ax.plot(*vizedge.T, color='gray', alpha=0.5)
512# Plot nodes
513ax.scatter(*node_xyz.T, s=100, c='lightblue', edgecolors='black')
515# Labels
516for node, (x, y, z) in zip(G, node_xyz):
517 ax.text(x, y, z, str(node))
519ax.set_axis_off()
520plt.show()
521```

3D Network Plot

import matplotlib.pyplot as plt
import numpy as np

# 3D spring layout
pos = nx.spring_layout(G, dim=3, seed=42)

# Extract coordinates
node_xyz = np.array([pos[v] for v in G.nodes()])
edge_xyz = np.array([(pos[u], pos[v]) for u, v in G.edges()])

# Create figure
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, projection='3d')

# Plot edges
for vizedge in edge_xyz:
    ax.plot(*vizedge.T, color='gray', alpha=0.5)

# Plot nodes
ax.scatter(*node_xyz.T, s=100, c='lightblue', edgecolors='black')

# Labels
for node, (x, y, z) in zip(G, node_xyz):
    ax.text(x, y, z, str(node))

ax.set_axis_off()
plt.show()
Raw lines 492 to 522
523## Best Practices

Best Practices

Raw lines 523 to 524
525### Performance
526- For large graphs (>1000 nodes), use simpler layouts (circular, random)
527- Use `alpha` parameter to make dense edges more visible
528- Consider downsampling or showing subgraphs for very large networks

Performance

  • For large graphs (>1000 nodes), use simpler layouts (circular, random)
  • Use alpha parameter to make dense edges more visible
  • Consider downsampling or showing subgraphs for very large networks
Raw lines 525 to 529
530### Aesthetics
531- Use consistent color schemes
532- Scale node sizes meaningfully (e.g., by degree or importance)
533- Keep labels readable (adjust font size and position)
534- Use white space effectively (adjust figure size)

Aesthetics

  • Use consistent color schemes
  • Scale node sizes meaningfully (e.g., by degree or importance)
  • Keep labels readable (adjust font size and position)
  • Use white space effectively (adjust figure size)
Raw lines 530 to 535
536### Reproducibility
537- Always set random seeds for layouts: `nx.spring_layout(G, seed=42)`
538- Save layout positions for consistency across multiple plots
539- Document color/size mappings in legends or captions

Reproducibility

  • Always set random seeds for layouts: nx.spring_layout(G, seed=42)
  • Save layout positions for consistency across multiple plots
  • Document color/size mappings in legends or captions
Raw lines 536 to 540
541### File Formats
542- PNG for raster images (web, presentations)
543- PDF for vector graphics (publications, scalable)
544- SVG for web and interactive applications
545- HTML for interactive visualizations

File Formats

  • PNG for raster images (web, presentations)
  • PDF for vector graphics (publications, scalable)
  • SVG for web and interactive applications
  • HTML for interactive visualizations
Raw lines 541 to 545