NetworkX add node after spring_layout to the graph

Viewed 445

Having the following code:

import networkx as nx
import matplotlib.pyplot as plt

G = nx.Graph()
G.add_nodes_from(range(1, 10))
G.add_edges_from([(1, 3), (2, 4), (3, 4), (2,6), (1, 2), (4, 9), (9, 1)])
pos = nx.spring_layout(G)
nx.draw(G, pos, with_labels=True)
plt.show()
G.add_node(10)
nx.draw(G, pos, with_labels=True) # this gives the error
plt.show()

How can I add node 10 to the graph at a random position? The error I'm actually getting is:

NetworkXError: Node 10 has no position.

How can I include the newly created node to the graph already built spring_layout?

2 Answers

The problem (as already noted by others) is that pos is a dict which assigns a position to each node. But when you've added a node, it doesn't update pos.

The following will find a good position for new node 10 given the existing position of all the other nodes. Basically, it calls spring_layout again, but holds all of the existing nodes in place. I've got node 10 connected to node 9.

import networkx as nx
import matplotlib.pyplot as plt

G = nx.Graph()
G.add_nodes_from(range(1, 10))
G.add_edges_from([(1, 3), (2, 4), (3, 4), (2,6), (1, 2), (4, 9), (9, 1)])
pos = nx.spring_layout(G)
nx.draw(G, pos, with_labels=True)
plt.show()

G.add_node(10)
G.add_edge(9,10)  #So node 10 should be close to node 9
oldnodes = list(G.nodes())
oldnodes.remove(10)
pos = nx.spring_layout(G, pos=pos, fixed=oldnodes)

nx.draw(G, pos, with_labels=True) 
plt.show()

The output from spring layout is a dictionary mapping nodes to positions {nodeid:[x,y]}. To place the new node randomly, you have to give it a random position in the pos dictionary.

Here is an example that finds the bounding box and then picks a random point somewhere inside.

import numpy as np

bounds = np.zeros((2,2)) # xy min, xymax

for pt in pos.values():
    bounds[0] = np.min([bounds[0],pt], axis=0) # compare point to bounds and take the lower value
    bounds[1] = np.max([bounds[1],pt], axis=0) # compare point to bounds and take the highest value

pos[10] = (bounds[1] - bounds[0]) * np.random.random(2)  + bounds[0]
Related