How to add a key to a graph drawing?

Viewed 397

I have created a graph using networkx. When I draw this graph the node labels do not fit (node names can be pretty long), so I have replaced them by numeric indices. The problem with this workaround is that the resulting drawing is harder to interpret as those numbers are meaningless. This is my code:

import networkx as nx
import matplotlib.pyplot as plt

G = nx.Graph()
G.add_nodes_from(['First', 'Second', 'Third'])
G.add_edges_from([('First', 'Second'), ('First', 'Third'), ('Second', 'Third')])
name2num = {name: num + 1 for num, name in enumerate(list(G.nodes))}
H = nx.relabel_nodes(G, mapping=name2num, copy=True)

fig, (ax0, ax1) = plt.subplots(1, 2)
nx.draw(G, ax=ax0, with_labels=True)
nx.draw(H, ax=ax1, with_labels=True)

graphs
My question is: how could I add a key to the drawing on the right?
This is the information I'd like to display:

1 - First
2 - Second
3 - Third

I tried to add a legend, to no avail:

ax0.legend(list(name2num.values()), list(name2num.keys()))

PS: I found a number of threads related to my problem. The proposed solutions consist in encoding the node labels through different colors. I'd rather prefer to encode the node labels through numbers.

2 Answers

Instead of using a ax.legend you could place a text box:

import networkx as nx
import matplotlib.pyplot as plt

G = nx.Graph()
G.add_nodes_from(["First", "Second", "Third"])
G.add_edges_from([("First", "Second"), ("First", "Third"), ("Second", "Third")])
name2num = {name: num + 1 for num, name in enumerate(list(G.nodes))}
H = nx.relabel_nodes(G, mapping=name2num, copy=True)

fig, (ax0, ax1) = plt.subplots(1, 2)
nx.draw(G, ax=ax0, with_labels=True)
nx.draw(H, ax=ax1, with_labels=True)


legend_text = "\n".join(f"{v} - {k}" for k, v in name2num.items())
props = dict(boxstyle="round", facecolor="w", alpha=0.5)
ax1.text(
    1.15,
    0.95,
    legend_text,
    transform=ax1.transAxes,
    fontsize=14,
    verticalalignment="top",
    bbox=props,
)

Network figure with text box legend

You could use nx.draw_networkx_labels and use the defined dictionary name2num to map the labels in the graph on the second axis. Note that you don't need to create a new graph with renamed labels, just plot the same, disabling with_labels and instead using the dictionary:

name2num = {name: f'{num}-{name}' for num, name in enumerate(list(G.nodes), 1)}

With this you'd get:

fig, (ax0, ax1) = plt.subplots(1, 2)

posG_renamed = nx.spring_layout(G)

nx.draw(G, ax=ax0, with_labels=True,
       node_size = 2000, node_color='lightblue')

nx.draw(G, pos=posG_renamed, ax=ax1, 
        node_size = 2000, node_color='lightgreen')

nx.draw_networkx_labels(G, posG_renamed, ax=ax1,
                        labels=name2num,
                        font_size=12)

enter image description here

Related