Skip to content Skip to sidebar Skip to footer

Networkx In A Subplot Is Drawing Nodes Partially Outside Of Axes Frame

When I draw a networkx graph in a subplot, some of the nodes are partially cut off in the frame of the axes. I've tried this with all different types of graphs and layouts, it's al

Solution 1:

Background

Your issue seems to be caused by the new autoscaling algorithm introduced with matplotlib 3.2.0. In the link it states, that the old algorithm did

for Axes.scatter it would make the limits large enough to not clip any markers in the scatter.

Hence, the new algorithm has stopped to do this, which results in the cute nodes.

How to fix your problem

You can simply increase the length of your axis:

import networkx as nx
import matplotlib.pylab as plt

figure = plt.subplot(2, 1, 1)
plt.scatter(range(10), range(10))

plt.subplot(2, 1, 2)
G = nx.erdos_renyi_graph(20, p=0.1)
nx.draw_networkx(G)
axis = plt.gca()
# maybe smaller factors work as well, but 1.1 works fine for this minimal example
axis.set_xlim([1.1*x for x in axis.get_xlim()])
axis.set_ylim([1.1*y for y in axis.get_ylim()])
plt.show()

Solution 2:

Just playing a with the figure sizes should do the trick. Try setting a larger figure size through the subplots' figsize parameter:

f, axs = plt.subplots(2,1,figsize=(15,15))
axs[0].scatter(range(10), range(10))
G = nx.erdos_renyi_graph(20, p=0.1)
nx.draw_networkx(G, ax=axs[1], node_color='lightgreen')

enter image description here


You can also look into networkX' layouts, such as spring_layout, which allow to encapsulate the nodes within a given box size, specified by a scale parameter. Here's an example:

f, axs = plt.subplots(2,1,figsize=(15,15))
axs[0].scatter(range(10), range(10))
G = nx.erdos_renyi_graph(20, p=0.05)
pos = nx.spring_layout(G, k=0.7, scale=0.05)
nx.draw_networkx(G, pos=pos, ax=axs[1], node_color='lightgreen')

enter image description here

Solution 3:

Since the other answers require the user to adjust some parameter manually in an iterative process, I wanted to add my own answer. It is automatic, but the current implementation only works if all node sizes are equal.

Node sizes are in points, therefore they don't scale with the image. Although this answer works programmatically, it doesn't work if you interactively change the window size of the figure. The first half of the fix_graph_scale function calculates the node radius in terms of the future x and y scale. The second half sets the axis scales such that they include all node positions plus half of the node size.

The get_ax_size function is from unutbu's answer with slight modifications.

import matplotlib.pyplot as plt
import networkx as nx

defget_ax_size(ax):
    bbox = ax.get_window_extent().transformed(ax.figure.dpi_scale_trans.inverted())
    width, height = bbox.width, bbox.height
    width *= 72
    height *= 72return width, height

deffix_graph_scale(ax,pos,node_size = 300):

    node_radius = (node_size / 3.14159265359)**0.5

    min_x = min(i_pos[0] for i_pos in pos.values())
    max_x = max(i_pos[0] for i_pos in pos.values())
    min_y = min(i_pos[1] for i_pos in pos.values())
    max_y = max(i_pos[1] for i_pos in pos.values())

    ax_size_x, ax_size_y = get_ax_size(ax)
    points_to_x_axis = (max_x - min_x)/(ax_size_x-node_radius*2)
    points_to_y_axis = (max_y - min_y)/(ax_size_y-node_radius*2)
    node_radius_in_x_axis = node_radius * points_to_x_axis
    node_radius_in_y_axis = node_radius * points_to_y_axis

    ax_min_x = min_x - node_radius_in_x_axis
    ax_max_x = max_x + node_radius_in_x_axis
    ax_min_y = min_y - node_radius_in_y_axis
    ax_max_y = max_y + node_radius_in_y_axis

    ax.set_xlim([ax_min_x, ax_max_x])
    ax.set_ylim([ax_min_y, ax_max_y])

fig, (ax1, ax2) = plt.subplots(2, 1)
ax1.scatter(range(10), range(10))

G = nx.erdos_renyi_graph(20, p=0.1)
pos = nx.drawing.spring_layout(G)
nx.draw_networkx(G,pos,ax=ax2)

default_node_size = 300
fix_graph_scale(ax2,pos,node_size = default_node_size)
plt.show()

Sample result

Post a Comment for "Networkx In A Subplot Is Drawing Nodes Partially Outside Of Axes Frame"