Say I have two networkx graphs, G
and H
:
G=nx.Graph() fromnodes=[0,1,1,1,1,1,2] tonodes=[1,2,3,4,5,6,7] for x,y in zip(fromnodes,tonodes): G.add_edge(x,y) H=nx.Graph() fromnodes=range(2,8) tonodes=range(8,14) for x,y in zip(fromnodes,tonodes): H.add_edge(x,y)
What is the best way to join the two networkx graphs?
I’d like to preserve the node names (note the common nodes, 2 to 7). When I used nx.disjoint_union(G,H)
, this did not happen:
>>> G.nodes() [0, 1, 2, 3, 4, 5, 6, 7] >>> H.nodes() [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] >>> Un= nx.disjoint_union(G,H) >>> Un.nodes() [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] #
The H
node labels were changed (not what I want). I want to join the graphs at the nodes with the same number.
Note. This is not a duplicate of Combine two weighted graphs in NetworkX
Advertisement
Answer
The function you’re looking for is compose, which produces a graph with all the edges and all the nodes that are in both graphs. If both graphs have a node with the same name, then a single copy ends up in the new graph. Similarly if the same edge exists in both. Here’s an example, including edge/node attributes:
import networkx as nx G=nx.Graph() G.add_node(1, weight = 2) G.add_node(2, weight = 3) G.add_edge(1,2, flux = 5) G.add_edge(2,4) H=nx.Graph() H.add_node(1, weight = 4) H.add_edge(1,2, flux = 10) H.add_edge(1,3) F = nx.compose(G,H) #F has all nodes & edges of both graphs, including attributes #Where the attributes conflict, it uses the attributes of H. G.nodes(data=True) > NodeDataView({1: {'weight': 2}, 2: {'weight': 3}, 4: {}}) H.nodes(data=True) > NodeDataView({1: {'weight': 4}, 2: {}, 3: {}}) F.nodes(data=True) > NodeDataView({1: {'weight': 4}, 2: {'weight': 3}, 4: {}, 3: {}}) G.edges(data=True) > EdgeDataView([(1, 2, {'flux': 5}), (2, 4, {})]) H.edges(data=True) > EdgeDataView([(1, 2, {'flux': 10}), (1, 3, {})]) F.edges(data=True) EdgeDataView([(1, 2, {'flux': 10}), (1, 3, {}), (2, 4, {})])
These preserve attributes, but obviously if there is a conflict this is not possible. The attributes of H
take precedence.
There are also other options to do the symmetric difference, intersection, …
If you have multiple graphs to join together, you can use compose_all
, which just wraps a for loop around compose
.