Natasha
Natasha

Reputation: 1521

Sorting the nodes of a Networkx graph

I have the following graph to which I delete and add nodes, edges.

import networkx as nx
import matplotlib.pyplot as plt

G = nx.gnm_random_graph(n=10, m=15, seed=1)
pos = nx.spring_layout(G)
print(pos)
nx.set_node_attributes(G, pos, 'pos')
G.remove_edge(2, 9)
largest_cc = max(nx.connected_components(G), key=len)
G = G.subgraph(largest_cc).copy()
G.add_node(2, pos=pos[2])
G.add_edge(2, 8)
print(G.edges)
print(nx.get_node_attributes(G, 'pos'))
print(G.nodes)

The final outputs aren't sorted, the following is the numbering if the nodes (attributes aren't sorted as well)

print(G.nodes)
[0, 1, 3, 4, 5, 6, 7, 8, 9, 2]

Expected output:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

I would like to know how to create a sorted graph.

Upvotes: 3

Views: 7206

Answers (2)

yatu
yatu

Reputation: 88236

By building a subgraph using the nodes in the largest connected component, you're removing that second node:

G = nx.gnm_random_graph(n=10, m=15, seed=1)
pos = nx.spring_layout(G)
nx.set_node_attributes(G, pos, 'pos')

G.remove_edge(2, 9)
largest_cc = max(nx.connected_components(G), key=len)
G.nodes()
# NodeView((0, 1, 2, 3, 4, 5, 6, 7, 8, 9))

G = G.subgraph(largest_cc).copy()
G.nodes()
# NodeView((0, 1, 3, 4, 5, 6, 7, 8, 9))

Now by adding node 2 again, G.add_node(2, pos=pos[2]), this is essentially updating the node data dictionary (the internal data structure in which it is saved), literally with dict.update:

d = dict(G.nodes(data=True))
d.update({2:{'pos':[0.3, 0.5]}})
print(d)
{0: {'pos': array([ 0.33041585, -0.07185971])},
 1: {'pos': array([-0.19659528,  0.33972794])},
 3: {'pos': array([ 0.22691433, -0.1802301 ])},
 4: {'pos': array([0.22462413, 0.2452357 ])},
 5: {'pos': array([ 0.65037774, -0.18057473])},
 6: {'pos': array([-0.14587125, -0.13225175])},
 7: {'pos': array([0.05279257, 0.10579408])},
 8: {'pos': array([ 0.42384353, -0.46262269])},
 9: {'pos': array([-0.56650162,  0.13495046])},
 2: {'pos': [0.3, 0.5]}}

Hence the node is appended as a new dictionary key/value pair,

G.add_node(2, pos=pos[2])
G.add_edge(2, 8)

G.nodes()
# NodeView((0, 1, 3, 4, 5, 6, 7, 8, 9, 2))

There is Graph.add_nodes_from, but it only updates the attributes if the node exists (does not remove and add the node anew), which makes sense:

G.add_nodes_from(sorted(G.nodes(data=True)))
G.nodes()
NodeView((0, 1, 3, 4, 5, 6, 7, 8, 9, 2))

So the way to go, is creating a graph anew, and assigning the sorted nodes, as in warped's answer:

H = nx.Graph()
H.add_nodes_from(sorted(G.nodes(data=True)))
H.add_edges_from(G.edges(data=True))

H.nodes()
# NodeView((0, 1, 2, 3, 4, 5, 6, 7, 8, 9))

Upvotes: 1

warped
warped

Reputation: 9481

A simple workaround would be to copy the nodes into a new graph:

H = nx.Graph()
H.add_nodes_from(sorted(G.nodes(data=True)))
H.add_edges_from(G.edges(data=True))

Upvotes: 4

Related Questions