Combine (join) networkx Graphs

PythonGraph TheoryNetworkx

Python Problem Overview


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 https://stackoverflow.com/questions/21806751/combine-two-weighted-graphs-in-networkx.

Python Solutions


Solution 1 - Python

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.

Solution 2 - Python

This did it.

   U=nx.Graph()
   U.add_edges_from(G.edges()+H.edges())
   U.add_nodes_from(G.nodes()+H.nodes()) #deals with isolated nodes

or, preserving the edge attributes:

   U.add_edges_from(G.edges(data=True)+H.edges(data=True))

and, to also preserve the node attributes:

   U.add_nodes_from(G.nodes(data=True)+H.nodes(data=True))

Solution 3 - Python

In case you want to add graph H to G then return G, you can use update method.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionatomh33lsView Question on Stackoverflow
Solution 1 - PythonJoelView Answer on Stackoverflow
Solution 2 - Pythonatomh33lsView Answer on Stackoverflow
Solution 3 - PythonTran CuongView Answer on Stackoverflow