Choosing NetworkX Graph vs MultiGraph for Production Data with Duplicate Edges
0 reputation · 26 Jan 2026, 18:31 UTC
0 reputation · 26 Jan 2026, 18:31 UTC
When building a NetworkX graph from an edge list that may contain multiple edges between the same node pair, the local test set often contains no duplicates, so a simple nx.Graph works. In production, duplicate edges appear and the Graph class silently overwrites the attribute dictionary of the existing edge, keeping only the last set of attributes.
The alternative is to use nx.MultiGraph, which preserves each parallel edge with a distinct key, but this changes the shape of edge‑access tuples ((u, v, key, data)) and makes neighbor lookups keyed, while the auto‑generated keys are not stable after modifications. The decision hinges on whether to preprocess the data to merge duplicate attributes into a single edge or to adopt MultiGraph and update all downstream algorithms to handle keys.
Should duplicate edges be merged into a single attribute dictionary before insertion, or should the codebase switch to MultiGraph and adapt edge‑iteration logic? How does the choice affect attribute preservation, traversal complexity, and the stability of edge identifiers in subsequent graph operations?
35275 reputation · 27 Jan 2026, 03:16 UTC
When the edge list contains duplicates, a plain nx.Graph will silently keep only the last attribute set for a pair of nodes. A nx.MultiGraph preserves every duplicate as a separate edge with its own key, but it changes the shape of edge tuples and can affect algorithms that expect a simple edge representation.
Graph overwrites; MultiGraph keeps all.Graph yields (u, v, data); MultiGraph yields (u, v, key, data).MultiGraph are integers that can shift when edges are removed or re‑added.MultiGraph stores an extra dictionary per parallel edge, which can increase memory usage and the cost of algorithms that iterate over all edges.If the downstream logic only needs a single edge per node pair and the attribute values can be aggregated (e.g., summing weights, concatenating lists), merging duplicates is the simplest path. It keeps the graph type unchanged and avoids touching existing code that iterates over G.edges(data=True).
import networkx as nx
G = nx.Graph()
# example: sum weights
for u, v, data in raw_edges:
if G.has_edge(u, v):
G[u][v]['weight'] += data.get('weight', 0)
else:
G.add_edge(u, v, **data)
Use nx.MultiGraph when:
After switching, update all edge‑access patterns:
# old: (u, v, data)
for u, v, data in G.edges(data=True):
...
# new: (u, v, key, data)
for u, v, key, data in G.edges(keys=True, data=True):
...
edge_counts = {(u, v): 0 for u, v in raw_edges}
for u, v, _ in raw_edges:
edge_counts[(u, v)] += 1
duplicates = [k for k, c in edge_counts.items() if c > 1]
print('Duplicates:', duplicates)
G = nx.Graph()
G.add_edge(1, 2, weight=1)
G.add_edge(1, 2, weight=2)
print(G[1][2]) # shows weight 2
MG = nx.MultiGraph()
MG.add_edge(1, 2, weight=1)
MG.add_edge(1, 2, weight=2)
print(list(MG.edges(keys=True, data=True)))
# shows two entries with keys 0 and 1
Graph.
MultiGraph and update code. If no, merge duplicates as shown above.MultiGraph keeps all; Graph loses earlier ones.MultiGraph adds a key dimension; algorithms that ignore keys may need adjustment.MultiGraph, keys are stable only while the graph structure remains unchanged; deletions or re‑additions can shift them.Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.