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:
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()
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()