Search code examples
pythongraphnodesnetworkxedges

How to add edge weights from one graph to matching edges in a different graph in NetworkX?


I have two different graphs in networkx, one graph has a total collection of edges. The other graph is a subset of the total edges. How would I take the weights from the total collection of edges graph and add them to matching edges in the new graph?

#total edge collection
G.edges(data = True)

OutEdgeDataView([(1, 2, {'weight': 10}), (2, 3, {'weight': 0}), (2, 5, {'weight': 0}), (2, 6, {'weight': 0}), 
(2, 1, {'weight': 0}), (3, 4, {'weight': 10}), (3, 7, {'weight': 0}), (3, 8, {'weight': 0}), (3, 2, {'weight': 0}), (4, 3, {'weight': 0}), (5, 2, {'weight': 0}), (6, 2, {'weight': 0}), 
(7, 3, {'weight': 0}), (8, 3, {'weight': 0})])
T = nx.Graph()
T.add_edges_from([(1, 2), (2, 3), (2, 5), (2, 6), (3, 8), (3, 4), (3, 7)])
T.edges(data = True)

EdgeDataView([(1, 2, {}), (2, 3, {}), (2, 5, {}), (2, 6, {}), (3, 8, {}), (3, 4, {}), (3, 7, {})])

I would want the T EdgeDataView to look like

EdgeDataView([(1, 2, {'weight':10}), (2, 3, {'weight': 0}), (2, 5, {'weight': 0}), (2, 6, {'weight': 0}),
 (3, 8, {'weight': 0}), (3, 4, {'weight': 10}), (3, 7, {'weight': 0})])

Any ideas would be appreciated,


Solution

  • You may try the networkx Graph.edge_subgraph function.

    For your example.
    First creating the graph:

    G = nx.DiGraph()
    G.add_edges_from([(1, 2, {'weight': 10}), (2, 3, {'weight': 0}), (2, 5, {'weight': 0}), (2, 6, {'weight': 0}), 
    (2, 1, {'weight': 0}), (3, 4, {'weight': 10}), (3, 7, {'weight': 0}), (3, 8, {'weight': 0}), (3, 2, {'weight': 0}), (4, 3, {'weight': 0}), (5, 2, {'weight': 0}), (6, 2, {'weight': 0}), 
    (7, 3, {'weight': 0}), (8, 3, {'weight': 0})])
    

    Next, choose the nodes you pretend to add to a new graph:

    edge_set = [(1, 2), (2, 3), (2, 5), (2, 6), (3, 8), (3, 4), (3, 7)]
    

    Then, extract the edges from one graph to the other:

    Di_T = G.edge_subgraph(edge_set)
    

    Note that since G is directed T will also be directed, so:

    T = Di_T.to_undirected()    # see NOTE in the end
    

    Result

    >>> T.edges(data = True)
    
    EdgeDataView([ (1, 2, {'weight': 10}),
                   (2, 3, {'weight': 0}),
                   (2, 5, {'weight': 0}),
                   (2, 6, {'weight': 0}),
                   (3, 4, {'weight': 10}),
                   (3, 7, {'weight': 0}),
                   (3, 8, {'weight': 0})])
    

    full code:

    # example graph
    
    G = nx.DiGraph()
    G.add_edges_from([(1, 2, {'weight': 10}), (2, 3, {'weight': 0}), (2, 5, {'weight': 0}), (2, 6, {'weight': 0}), (2, 1, {'weight': 0}), (3, 4, {'weight': 10}), (3, 7, {'weight': 0}), (3, 8, {'weight': 0}), (3, 2, {'weight': 0}), (4, 3, {'weight': 0}), (5, 2, {'weight': 0}), (6, 2, {'weight': 0}), (7, 3, {'weight': 0}), (8, 3, {'weight': 0})])
    
    
    # example edge set
    
    edge_set = [(1, 2), (2, 3), (2, 5), (2, 6), (3, 8), (3, 4), (3, 7)]
    
    
    # solution
    
    T = G.edge_subgraph(edge_set).to_undirected()
    T.edges(data = True)
    

    NOTE:

    Usually a copy is made of G.edge_subgraph(edge_set) (using .copy) in order to obtain a new copy of the graph instead of a reference of the original graph(see the notes in the Docs).
    However, .to_undirected already makes a deep copy of the graph so there is no need for .copy, check G.edge_subgraph and .to_undirected documentations for more info