Search code examples
pythonnetworkx

Networkx draw graph and show node attributes in a dict


I have a graph where each node has two attributes 'Name' and 'Type'.
I want to draw the graph in a way that it is able to print both the attributes and the node name in the same plot. Currently, I am able to print them in one single plot itself but the text gets overlapped.
The code I currently use is this:

# drawing the graph with the nodes labelled
fig, ax = plt.subplots(nrows=3, figsize=(10,10))
pos = nx.spring_layout(graph, k=5)
# drawing the graph only
nx.draw(graph, pos, ax[0], with_labels=True, edge_color=edge_color)

# getting node labels
names = nx.get_node_attributes(graph, 'Name')
nx.draw(graph, pos, ax=ax[1])
nx.draw_networkx_labels(graph, pos, labels=names, ax=ax[1])

types = nx.get_node_attributes(graph, 'Type')
nx.draw_networkx_labels(graph, pos, labels=types, ax=ax[1])
plt.show()

Right now I am drawing separate graphs for the attributes and the node labels. My current code overlaps the labels and the attributes as shown in the image below:enter image description here

The first plot contains the node labels and the second plot shows the name and type attributes but they're overlapped.
How do I format the attribute texts such that they don't overlap?


Solution

  • The simplest way to prevent text items from overlapping with each other is to join them into a single, properly formatted text object.

    labels = dict()
    for node in graph.nodes:
        labels[node] = f"{names[node]}\n{types[node]}"
    nx.draw_networkx_labels(graph, pos, labels=labels, ax=ax[1])
    

    This will join the name and type entries into a single string, separated by a newline.

    Properly dealing with the overlaps between nodes and labels is harder, as networkx has no collision detection between plot elements. I have outlined how this can be achieved in netgraph, a network visualisation library I wrote some time ago, in this answer here.