Home > Back-end >  Networkx: Replacing labels of nodes
Networkx: Replacing labels of nodes

Time:01-03

I have the following minimal code:

import networkx as nx
import matplotlib.pyplot as plt

G = nx.DiGraph()
#G = nx.Graph()
#G = nx.path_graph(4)

pos1 = {0: (0, 0), 1: (2, 1), 2: (2, 0), 3: (2,-1)}
G.add_edge(0, 1)
G.add_edge(0, 3)
G.add_edge(1, 2)
G.add_edge(2, 3)

# First Network
plt.figure(0)
nx.draw_networkx(G, pos1) # Puts numbers as labels of nodes
plt.axis("off")
plt.savefig('graph1.png')

# Second network 
plt.figure(1)
mapping = {0: "Zero", 1: "One", 2: "Two", 3: "Three"}
H = nx.relabel_nodes(G, mapping)
nx.draw_networkx(H)  # Works

''' The below line I want to modify '''
#nx.draw_networkx(H, pos1) # Doesn't work  
                          # Says: NetworkXError: Node 'Zero' has no position 

plt.axis("off")
plt.savefig('graph2.png')
plt.show() 

Here I am trying to replace the label names in the new graph H. But it shows an error since I am using coordinates for the nodes.

Right now the outputs are:

Graph 1

Graph 2

The second graph needs to be corrected. Also, can the sizes of the nodes be auto-adjusted and even-odd numbered (labels for the first network) nodes be colored differently?

PS. If networkx has limitations, then an example with some other module may also serve the purpose.

CodePudding user response:

The simplest approach would be to create a relabelled pos dictionary using the new node names:

pos1 = {0: (0, 0), 1: (2, 1), 2: (2, 0), 3: (2,-1)}
mapping = {0: "Zero", 1: "One", 2: "Two", 3: "Three"}
pos_new = {mapping[k]: v for k, v in pos1.items()}
# use the above with nx.draw_networkx(H, pos_new)

CodePudding user response:

I think the best way to solve this is to not use the nx.draw_networkx command but rather the separate draw commands for labels, nodes and edges. With nx.draw_networkx_labels you can pass your dictionary directly without changing your nodes names:

import networkx as nx
import matplotlib.pyplot as plt

G = nx.DiGraph()

pos1 = {0: (0, 0), 1: (2, 1), 2: (2, 0), 3: (2,-1)}
G.add_edge(0, 1)
G.add_edge(0, 3)
G.add_edge(1, 2)
G.add_edge(2, 3)

node_colors = ['red'if i%2==0 else 'blue' for i in G.nodes]
mapping = {0: "Zero", 1: "One", 2: "Two", 3: "Three"}

plt.figure()

nx.draw_networkx_nodes(G, pos=pos1,node_color=node_colors, node_size=500)
nx.draw_networkx_edges(G, pos=pos1)
nx.draw_networkx_labels(G, pos=pos1, labels=mapping)

plt.axis("off")
plt.show() 

This produces:enter image description here

If you want to fit the node sizes to the labels, manipulate them. If you only care about the text, not about the node itself. Don't use the nx.draw_networkx_nodes command, instead add the bbox argument to nx.draw_networkx_labels. Like so:

plt.figure()

#nx.draw_networkx_nodes(G, pos=pos1,node_color=node_colors, node_size=500)
nx.draw_networkx_edges(G, pos=pos1)
nx.draw_networkx_labels(G, pos=pos1, labels=mapping, bbox ={})

plt.axis("off")
plt.show() 

Which produces:enter image description here

  • Related