'How to plot without extending axis limits?
I'm trying to draw on an existing axis without extending or modifying its limits.
For example:
import numpy as np
import matplotlib.pyplot as plt
xy = np.random.randn(100, 2)
plt.scatter(xy[:,0], xy[:,1])
Makes a fine plot with well-fitting axis limits.
However, when I try to draw a line on top of it:
xlim = plt.gca().get_xlim()
plt.plot(xlim, xlim, 'k--')
the axis limits are extended, presumably to create padding around the new data.
How can I draw a line without this padding?
Solution 1:[1]
Setting plt.autoscale(False) prevents autoscaling from happening.
import numpy as np; np.random.seed(42)
import matplotlib.pyplot as plt
xy = np.random.randn(100, 2)
# By default plots are autoscaled.
plt.scatter(xy[:,0], xy[:,1])
#Turn autoscaling off
plt.autoscale(False)
xlim = plt.gca().get_xlim()
plt.plot(xlim, xlim, 'k--')
plt.show()
Solution 2:[2]
You can use the autoscale property of Axes objects:
Per the documentation:
Axes.autoscale(enable=True, axis='both', tight=None)Autoscale the axis view to the data (toggle).
Convenience method for simple axis view autoscaling. It turns autoscaling on or off, and then, if autoscaling for either axis is on, it performs the autoscaling on the specified axis or axes. Parameters:
enable : bool or None, optional True (default) turns autoscaling on, False turns it off. None leaves the autoscaling state unchanged. axis : {'both', 'x', 'y'}, optional which axis to operate on; default is 'both' tight: bool or None, optional If True, set view limits to data limits; if False, let the locator and margins expand the view limits; if None, use tight scaling if the only artist is an image, otherwise treat tight as False. The tight setting is retained for future autoscaling until it is explicitly changed.
fig, ax = plt.subplots()
ax.plot(np.random.normal(size=(100,)),np.random.normal(size=(100,)),'bo')
ax.autoscale(tight=True)
xlim = ax.get_xlim()
plt.plot(xlim, xlim, 'k--')
Solution 3:[3]
One brute-force solution is to keep track of the axis limits before drawing, and reset them after.
Like so:
from contextlib import contextmanager
@contextmanager
def preserve_limits(ax=None):
""" Plot without modifying axis limits """
if ax is None:
ax = plt.gca()
xlim = ax.get_xlim()
ylim = ax.get_ylim()
try:
yield ax
finally:
ax.set_xlim(xlim)
ax.set_ylim(ylim)
Now compare
plt.scatter(xy[:,0], xy[:,1])
xlim = plt.gca().get_xlim()
plt.plot(xlim, xlim, 'k--')
with
plt.scatter(xy[:,0], xy[:,1])
with preserve_limits():
xlim = plt.gca().get_xlim()
plt.plot(xlim, xlim, 'k--')
Solution 4:[4]
If you set the x-axis limits separately, they won't be overwritten until you change them, regardless of what is plotted. to make it mesh with your code, try:
plt.xlim(xlim)
when you get xlim, it gets the current limits, but once you 'set' them, they're locked until you change them again. This works for the y-axis as well, if you want those to be fixed too (just swap 'x' for 'y' and add the code).
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 | ImportanceOfBeingErnest |
| Solution 2 | |
| Solution 3 | |
| Solution 4 | Jgd |


