pythonmatplotlibgraphnetworkx

Networkx - how to use full canvas space


When generating a diagram with networkx and pyplot, the diagram is squashed in the middle with lots of empty white space around it.

import networkx as nx
import matplotlib.pyplot as plt

print(f"Building graph...")
g = nx.Graph()
"""
for loop to populate graph nodes and edges...
"""

print(f"Graph has {len(g.nodes)} nodes and {len(g.edges)} edges")

print(f"Generating layout...")
options = {"node_size": 10, "node_color": "blue", "font_color": "red"}
k = 1
i = 30
width = 60
height = 60
dpi = 60
pos = nx.spring_layout(g, k=k, iterations=i, seed=63)
_ = plt.figure(1, figsize=(width, height), dpi=dpi)
nx.draw_networkx(g, pos, **options)

print(f"Rendering graph...")
plt.axis("off")
filename = f"graph_{k}_{i}_{width}_{height}_{dpi}.png"
plt.savefig(filename, format="png")
print(f"Wrote to {filename}")
$ ./foo.py
Building graph...
Graph has 11843 nodes and 28054 edges
Generating layout...
Rendering graph...
Wrote to graph_1_30_60_60_60.png

Here is a screenshot of the rendered diagram (because they are upto 20MBs):

60x60 image with 60 dpi

As you can see, most of the diagram is empty white space around the graph in the center. Increasing the image width and height doesn't change this, nor increasing the DPI.

Here is a screenshot where the width, height, and DPI are all 100:

100x100 image with 100 dpi

The K value is set to a max of 1 (I kept raising it from the default of 0.1, with no improvement). I've tried to increase the iterations to 100 with no significant improvement.

The problem I am trying to solve here is that the graph in the middle is too crowded. It can't see it from the screenshots, but the node labels are readable when zooming in, however, some of the node labels overlap, so they need to be spread out more. If I keep increasing the image width and height, this does help a bit, but, the image size becomes really massive and most image viewers can't open the image.

Considering there is so much empty white space, I am trying to find a way to force the graph to spread out and use the full space of the canvas.


Solution

  • I fixed this by using a combination of technique:

    print(f"Rendering graph...")
    plt.axis("off")  # turn off axis
    plt.tight_layout()  # Reduce padding/margins
    plt.margins(0.0)  # Remove margins
    filename = f"graph_{k}_{i}_{width}_{height}_{dpi}.png"
    plt.savefig(filename, format="png", bbox_inches='tight')
    print(f"Wrote to {filename}")
    

    Each one remove a bit more white space and the combination together has removed all excess white space.