Skip to main content
Source Link
cottontail
  • 26.5k
  • 26
  • 204
  • 188

TL;DR: Change dpi

This is especially useful if you want to scale a figure without changing the size of every element in it. There are two ways one can set dpi: (a) pass it in a figure constructor via dpi= parameter, or (b) call to set_dpi on the figure instance. The following shows how to set dpi=50.

data = [3, 5, 1, 7, 6, 7, 2]

# case 1a
plt.figure(dpi=50)
plt.plot(data)

# case 1b
fig, ax = plt.subplots(dpi=50)
ax.plot(data)

# case #2
plt.plot(data)
plt.gcf().set_dpi(50)

The following image shows how dpi affects figure size. Note that figsize is the same for both figures.

result

If your plot is generated by a third party library such as pandas or seaborn, then you can access the figure instance using .figure on the Axes object and change its dpi.

# pandas example
s = pd.Series([3, 5, 1, 7, 6, 7, 2])
ax = s.plot()
ax.figure.set_dpi(72)   # <--- change dpi via Axes

# seaborn example
ax = sns.lineplot(s)
ax.figure.set_dpi(72)   # <--- change dpi via Axes

How does it work?

The size of every matplotlib element is determined by the interaction of three properties:

  1. Size in inches: Get current size via: fig.get_size_inches() and change it via fig.set_size_inches(). The default size is (6.4, 4.8).
  2. dpi (dots/pixels per inch): Get current dpi via: fig.get_dpi() and change it via fig.set_dpi(). The default dpi is 100. A figure using the default settings is drawn using 307,200 pixels(=6.4x100x4.8x100). By changing the number of pixels, we can change the size of the figure (and everything drawn on it such as lines, markers, ticklabels, borders, labels, titles etc.).
  3. ppi (points per inch): This is fixed at ppi=72. A point is the unit of matplotlib element size (linewidth, markersize, fontsize etc.). For example, a line with lw=1 is 1/72 inch wide, a letter with fontsize=10 is 10/72 inch tall etc. If dpi=100, lw=1 line is 100/72 pixels wide, a letter with fontsize=10 is 1000/72 pixels tall etc.

Suppose we have a figure with figsize=(4,2) and dpi=100. If we decrease the figwidth 4->2, then that change in pixels is 400->200. However, since ppi is constant, the size of everything on the plot stays the same, i.e. lw=1 line will still be 1/72" (100/72 pixels) wide even though the figure its drawn on is 200 pixels wide now. Visually, everything on a plot will look bigger/thicker relative to the figure size.

On the other hand, if we decrease dpi, everything becomes smaller proportionally. If we decrease dpi from 100 to 50, then the figwidth changes from 400 pixels to 200 pixels, lw=1 line changes from 100/72 pixels to 50/72 pixels wide, etc., in other words, the size of every element in pixels is halved.

comparison


Code used to produce the above figures:

for figsize, dpi in [((4,2), 100), ((4,2), 50), ((2,1), 100)]:
    plt.figure(figsize=figsize, dpi=dpi)
    plt.plot([3,5,1,7,6,7,2])
    plt.title(f"figsize={figsize}, dpi={dpi}")