'Preserve padding while setting an axis limit in matplotlib

Setting xlim and ylim for axis in pyplot removes the padding. How to set them without changing the padding?

Example:

fig, ax = plt.subplots()
x = np.linspace(0, 200, 500)
ax.set_ylim(ymax=100)
line = ax.plot(x, data, '--', linewidth=2, label='foo bar')
plt.show()

In the plot shown, x axis will have a padding while y axis don't. How to make them both have padding while having the ylim I want?



Solution 1:[1]

Axes.set_ymargin and Axes.set_ylim are mutually exclusive. Setting a limit to an axis overwrites the margin.

There are two options to have a margin (padding).

a. use margins

It's possible to adapt the margin using

ax.set_ymargin(0.1)   or   ax.margins(y=0.1)

where 0.1 would be a 10% margin on both axis ends. (Same for x axis of course). The drawback here is that the margin is always symmetric.

b. use limits

Using the limits set by ax.set_ylim(0, 100) and adapt them to the needs.
E.g. if data is the data to plot in form of a numpy array, and we want to have a 10% margin to the bottom and a 40% margin to the top, we could use

ymin = data.min()-0.1*(data.max()-data.min())
ymax = data.max()+0.4*(data.max()-data.min())
ax.set_ylim((ymin, ymax))

It would of course equally be possible to simply set ymax to ymax = 100, if this is desired.

Solution 2:[2]

With matplotlib 3.5, I used autoscaling as follows;

axs[row,column].plot(divs['Dividends'], c='red',linewidth=1, marker='.', mec='blue',mfc='blue')
axs[row,column].set_ylim(bottom = 0)        
axs[row,column].autoscale()

Solved this problem for me. See attached pics of the graphs for the difference autoscaling did.

Using .margins() with a value or 'tight=True' or .set_ymargin() didn't seem to do anything no matter what values I used to pad.

Changing the lower or bottom limit to <0 moved the Zero line well up the y axis when dividends in my examples are close to zero.

Graph with Autoscaling

Graph without Autoscaling

Solution 3:[3]

You can modify the ax.dataLim bounding box and reapply ax.autoscale_view()

Before:

fig, ax = plt.subplots()
x = np.linspace(0, 10, 11)
line = ax.plot(x, x, '--', linewidth=2, label='foo bar')

Before

After:

pts = ax.dataLim.get_points()  # numpy array [[xmin, ymin], [xmax, ymax]]
pts[1, 1] = 11  # new ymax
ax.dataLim.set_points(pts)
ax.autoscale_view()

enter image description here

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Community
Solution 2 LennyB
Solution 3