user6053895
user6053895

Reputation:

Match two nodes and keep the path between the other respective nodes networkx

EDITED

df1

From   description    To      priority 
10        Start      20,30       1
20        Left       40          2 
30        Right      40          2
40        End        -           1

My second data frame

df2

From   description    To      priority 
50        Start      60,70       1
60        Left       80          2 
70        Right      80          2
80        End        -           1

When I convert the two data frames into graph using Netwokrx Python library, I get the following graphs as graph1 for df1 and graph2 for df2. The color of the nodes is based on their priority.

enter image description here

I would like to match (combine) two nodes which have similar color such as 10/50, 40/80, 20/60, and 30/70. Just to make it clear, 10 and 50 have Start attribute and 40 and 80 have End. In addition to these, 10, 50, 40, and 80 have priority ==1 attribute. Node 20 and 60 have '''Left' attribute and 30 and 70 have Right. In addition to these, 20, 60, 30, and 70 have priority ==2.

I managed to match nodes at once for the whole nodes in the two graphs. But I couldn't manage to go step by step (using a kind of loop). Which means first match nodes with blue color then add one of the nodes with orange color and so on. I would expect something like below.

enter image description here

To achieve the above result, this how I tried.

for n1, n2 in g1.nodes(data ='True'):
    for x1, x2 in g2.nodes(data ='True'): 
        if ((g1.node[n1]['description']) == (g2.node[x1]['description'])&
            if ((g1.node[n1]['priority']) == (g2.node[x1]['priority'])
             ):
            name1 = str(n1) + '/' + str(x1)
            mapping1 = {n1: name1, x1:name1}
            mapping1 = nx.relabel_nodes(g1, mapping1, copy =True)

Can anyone extend the above trial or find a new solution to get what I would like to see?

Upvotes: 3

Views: 395

Answers (1)

Sparky05
Sparky05

Reputation: 4892

With the following code you can relabel the nodes:

More hints to the sorted function.

import networkx as nx

df1_graph = nx.DiGraph()
# add edges
df1_graph.add_edges_from([(10, 20), (10, 30), (20, 40), (30, 40)])
# add node information
nodes = [10, 20, 30, 40]
descriptions = ["Start", "Left", "Right", "End"]
priorities = [1, 2, 2, 1]
for node, (description, priority) in zip(nodes, zip(descriptions, priorities)):
    df1_graph.nodes[node]["description"] = description
    df1_graph.nodes[node]["priority"] = priority

df2_graph = nx.DiGraph()
# add edges
df2_graph.add_edges_from([(50, 60), (50, 70), (60, 80), (60, 80)])
nodes = [50, 60, 70, 80]
for node, (description, priority) in zip(nodes, zip(descriptions, priorities)):
    df2_graph.nodes[node]["description"] = description
    df2_graph.nodes[node]["priority"] = priority

# creating new graph
mappings = []
for node_1, data_1 in df1_graph.nodes(data=True):
    for node_2, data_2 in df2_graph.nodes(data=True):
        if data_1["description"] == data_2["description"] and data_1["priority"] == data_2["priority"]:
            name = str(node_1) + '/' + str(node_2)
            # add found mapping (node_1, name)
            # together with information about sorting order
            mappings.append((data_2["priority"], data_2["description"], node_1, name))

new_graph = df1_graph.copy()
# save the relabelled graphs in a lists
graphs_stepwise = []
# sort nodes according to priority and description (secondary key)
# we sort first by description to ensure in this example Left is replaced first
mappings = sorted(mappings, key=lambda x: x[1])
# sort by priority
mappings = sorted(mappings, key=lambda x: x[0])
# relabel one node at a time
for priority, description, node, new_label in mappings:
    new_graph = nx.relabel_nodes(new_graph, {node: new_label}, copy=True)
    graphs_stepwise.append(new_graph)

# print node information of saved graphs
for graph in graphs_stepwise:
    print(graph.nodes(data=True))
    #[(10, {'description': 'Start', 'priority': 1}), (20, {'description': 'Left', 'priority': 2}), (30, {'description': 'Right', 'priority': 2}), ('40/80', {'description': 'End', 'priority': 1})]
    #[('10/50', {'description': 'Start', 'priority': 1}), (20, {'description': 'Left', 'priority': 2}), (30, {'description': 'Right', 'priority': 2}), ('40/80', {'description': 'End', 'priority': 1})]
    #[('10/50', {'description': 'Start', 'priority': 1}), ('20/60', {'description': 'Left', 'priority': 2}), (30, {'description': 'Right', 'priority': 2}), ('40/80', {'description': 'End', 'priority': 1})]  
    #[('10/50', {'description': 'Start', 'priority': 1}), ('20/60', {'description': 'Left', 'priority': 2}), ('30/70', {'description': 'Right', 'priority': 2}), ('40/80', {'description': 'End', 'priority': 1})]

Upvotes: 2

Related Questions