29

I have a graph G with attribute 'state' for nodes and edges. I want to draw the graph, all nodes labelled, and with the state marked outside the corresponding edge/node.

for v in G.nodes():     
    G.node[v]['state']='X'
G.node[1]['state']='Y' 
G.node[2]['state']='Y'

for n in G.edges_iter():    
    G.edge[n[0]][n[1]]['state']='X'
G.edge[2][3]['state']='Y'

The command draw.networkx has an option for labels, but I do not understand how to provide the attribute as a label to this command. Could someone help me out?

cottontail
  • 10,268
  • 18
  • 50
  • 51
Bravo
  • 657
  • 1
  • 8
  • 19

2 Answers2

42

It's not so pretty - but it works like this:

from matplotlib import pyplot as plt
import networkx as nx
G = nx.Graph()
G.add_edge(1,2)
G.add_edge(2,3)
for v in G.nodes():
    G.node[v]['state']='X'
G.node[1]['state']='Y'
G.node[2]['state']='Y'

for n in G.edges_iter():
    G.edge[n[0]][n[1]]['state']='X'
G.edge[2][3]['state']='Y'

pos = nx.spring_layout(G)

nx.draw(G, pos)
node_labels = nx.get_node_attributes(G,'state')
nx.draw_networkx_labels(G, pos, labels = node_labels)
edge_labels = nx.get_edge_attributes(G,'state')
nx.draw_networkx_edge_labels(G, pos, labels = edge_labels)
plt.savefig('this.png')
plt.show()

enter image description here

Aric
  • 24,511
  • 5
  • 78
  • 77
  • 1
    Thanks, but I need a small modification. The labels of nodes are distinct from states. I need X and Y on top of the nodes and numbers like 1 and 2 inside them. – Bravo Dec 04 '13 at 17:44
  • 1
    If you need more sophisticated (and prettier) drawing of labels you might consider using Graphviz to do the drawing - graphivz.org. Output your graph from networkx (including with attributes if you want) to dot format using write_dot and then process that with Graphviz. – Aric Dec 04 '13 at 20:05
  • 2
    The positions of all of the nodes are in the "pos" dictionary. You can label them by hand using e.g. x,y=pos[1] and then plt.text(x,y,'label') – Aric Dec 04 '13 at 20:07
  • 1
    Is it possible to have only the value of the attribute printed? and not the key. For instance in this case, only 'X' printed and not 'state', how? – Riken Shah Feb 12 '17 at 07:03
  • 7
    @Kairos See 3rd last line `nx.draw_networkx_edge_labels(G, pos, labels = edge_labels)` change it to `nx.draw_networkx_edge_labels(G, pos, edge_labels)` – timekeeper Apr 13 '17 at 00:31
2

@Aric's solution is outdated and doesn't run anymore. The following code produces a similar graph. The only difference is that the plot below draws the node attributes separately from node labels.

import networkx as nx
# define a graph
G = nx.Graph()
edges = [(1, 2), (2, 3)]
G.add_edges_from(edges)

# set node attributes
for n in G.nodes:
    val = 'X' if n == 3 else 'Y'
    nx.set_node_attributes(G, {n: {'state': val}})
    
# set edge attributes
for e in G.edges:
    val = 'X' if e == (1, 2) else 'Y'
    nx.set_edge_attributes(G, {e: {'state': val}})

pos = nx.spring_layout(G, seed=0)

# get edge and node attributes
edge_labels = nx.get_edge_attributes(G, 'state')
node_states = nx.get_node_attributes(G, 'state')
# set node state positions
state_pos = {n: (x+0.12, y+0.05) for n, (x,y) in pos.items()}

# draw graph
nx.draw_networkx(G, pos, node_size=600)
# draw node state labels
nx.draw_networkx_labels(G, state_pos, labels=node_states, font_color='red')
# draw edge attributes
nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels);

result

cottontail
  • 10,268
  • 18
  • 50
  • 51