Charts end up in reports, papers and web pages, and the right format and resolution decide whether they look crisp or blurry.
fig.savefig("name.ext") writes the figure, and the extension picks the format. Choose by destination:
- PNG: raster, good for web pages, slides and screenshots. Set
dpi=(dots per inch); pixel size isfigsizetimesdpi, so a 6x4 inch figure at 200 dpi is 1200x800 pixels. - SVG and PDF: vector, so they scale without blurring; best for papers and print. Text stays text and file sizes stay small for simple plots, but huge scatter plots make large vector files.
- JPEG is supported (with Pillow) but blurs sharp lines; avoid it for charts.
Other useful arguments:
bbox_inches="tight"crops surrounding whitespace and includes labels that would otherwise be clipped.pad_inches=controls the margin left by the tight crop.transparent=Truemakes the background transparent, useful for slides with colored backgrounds.facecolor=sets the background color explicitly.
Fonts and line widths are specified in points, which are physical units. If text looks tiny in a saved image, the figure is too large in inches for its intended display size; reduce figsize instead of increasing every font.
Call savefig before plt.show() in scripts: after the window is closed, pyplot may have discarded the figure and you would save a blank image. In loops that create many figures, plt.close(fig) after saving releases the memory.
Example
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from PIL import Image
fig, ax = plt.subplots(figsize=(4, 3))
ax.plot([0, 1, 2], [2, 0, 1])
ax.set_ylabel("A label that might be clipped")
fig.savefig("chart.png", dpi=150)
fig.savefig("chart_tight.png", dpi=150, bbox_inches="tight")
fig.savefig("chart.svg") # vector, scales freely
plt.close(fig) # free memory in loops
print(Image.open("chart.png").size) # (600, 450) = 4x3 in * 150 dpi
print(Image.open("chart_tight.png").size[0] < 600) # True: whitespace croppedRemember
- The file extension picks the format: PNG for screens, SVG/PDF for print
- Pixel size = figsize (inches) x dpi
bbox_inches='tight'crops whitespace and avoids clipped labels
Watch out for
- Saving after
plt.show()in a script and getting an empty image.