16

When I draw a figure using matplotlib how do I save it without extra margins? Usually when I save it as

plt.savefig("figure.png") # or .pdf

I get it with some margins:

enter image description here

Example:

import matplotlib.pyplot as plt
import networkx as nx

G=nx.Graph()

G.add_edge('a','b',weight=1)
G.add_edge('a','c',weight=1)
G.add_edge('a','d',weight=1)
G.add_edge('a','e',weight=1)
G.add_edge('a','f',weight=1)
G.add_edge('a','g',weight=1)

pos=nx.spring_layout(G)
nx.draw_networkx_nodes(G,pos,node_size=1200,node_shape='o',node_color='0.75')

nx.draw_networkx_edges(G,pos,
                width=2,edge_color='b')

plt.axis('off')
plt.savefig("degree.png", bbox_inches="tight")
plt.show() 

Update 2:

The spaces are set inside the axes.. This is clear if I remove plt.axis('off')
So I think there is some trick to use with the package Networkx.

7 Answers 7

11

Try plt.savefig("figure.png", bbox_inches="tight").

Edit: Ah, you didn't mention you were using networkx (although now I see it's listed in a tag). bbox_inches="tight" is the way to crop the figure tightly. I don't know what networkx is doing, but I imagine it's setting some plot parameters that are adding extra space to the axes. You should look for a solution in networkx rather than matplotlib. (It may be, for instance, that networkx is adding the space inside the axes, not the figure; what does it look like if you remove that axis('off') call?)

Sign up to request clarification or add additional context in comments.

5 Comments

Can you give an example of what you mean by "margins"?
thank you. I do not want the figure to be saved with extra white spaces. I just want the borders to close the limits of the figure exactly. Is this clear?
This is exactly what bbox_inches="tight" does. Can you explain how it doesn't do what you want? Also what version of matplotlib are you using?
I think this is the version: Python 2.7 matplotlib-1.1.0
yes, you are right. the spaces are inside the axes. Thank you
9

add the codes below to control plot limits before saving.

try different values of cut, like from 1.05 to 1.50, until you see fit.

# adjust the plot limits
cut = 1.05
xmax= cut*max(xx for xx,yy in pos.values())
ymax= cut*max(yy for xx,yy in pos.values())
plt.xlim(0,xmax)
plt.ylim(0,ymax)

7 Comments

Thank you very much. It works but with removing some small part of the limits of the figure. I do not get the figure complete. So i think i just need to modify it somehow.
you can try a more conservative cut (1.10 or 1.05 rather than 1.02), just change it until the canvas fits.
@Aya you may want to ask the question on the networkx mailinglist, and also, you can try to wrap the above codes into a function so that you call it with whatever cut you want without copy&paste all the time.
NetworkX has to figure what the x limits are and y limits are based on the data and the node shape. There is just some simple padding of the exact data values to account for the node shape. You can adjust that using plt.xlim() and plt.ylim() as described above. Calling those functions with no arguments will give you the current limits.
this doesnt work. I tried with different values of cut, but i always get my figure 'cropped'
|
5

Use the following:

plt.margins(0.0)

1 Comment

Jurkiewics It worked with margins(0.15). margins(0.0) don't draw the graph totaly into the page.
1

I've recently stumbled upon a very nice solution:

import matplotlib.pyplot as plt
import networkx as nx


fig, ax = plt.subplots()

#We create our graph.
#...

#We remove the surrounding box.
plt.box(False)

#We save our graph.
fig.savefig(filename)

1 Comment

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
0

A bit of a hack, but if you use nx.draw, then it does a tighter fit.

So you could do

nx.draw(G,pos,node_size=1200,node_shape='o',node_color='0.75', edgelist = [])

which just draws the nodes and no edges. Then it's fine to do

nx.draw_networkx_edges(G, pos, width=2, edge_color='b')

Comments

0

To make the figure at the center you can use the following:

cut             = 1.1
xmax            = max(xx for xx,yy in pos.values())
ymax            = max(yy for xx,yy in pos.values())
xmin            = min(xx for xx,yy in pos.values())
ymin            = min(yy for xx,yy in pos.values())

xincrease       = (cut - 1)*xmax
yincrease       = (cut - 1)*ymax

plt.xlim(xmin - xincrease, cut*xmax)
plt.ylim(ymin - yincrease, cut*ymax)

Comments

-1

Without knowing the specifics of networkx I cannot be certain that this will work, but to remove the whitespace completely from the outside of an axes in matplotlib, you can do something along the lines of:

import matplotlib.pyplot as plt
ax = plt.axes([0, 0, 1, 1])
plt.plot(range(10))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.