I would like to plot a set of points using pyplot in matplotlib but have none of the points be on the edge of my axes. The autoscale (or something) sets the xlim
and ylim
such that often the first and last points lie at x = xmin
or xmax
making it difficult to read in some situations.
This is more often problematic with loglog()
or semilog()
plots because the autoscale would like xmin
and xmax
to be exact powers of ten, but if my data contains only three points, e.g. at xdata = [10**2,10**3,10**4]
then the first and last points will lie on the border of the plot.
This is my solution to add a 10% buffer to either side of the graph. But is there a way to do this more elegantly or automatically?
from numpy import array, log10
from matplotlib.pyplot import *
xdata = array([10**2,10**3,10**4])
ydata = xdata**2
figure()
loglog(xdata,ydata,'.')
xmin,xmax = xlim()
xbuff = 0.1*log10(xmax/xmin)
xlim(xmin*10**(-xbuff),xmax*10**(xbuff))
I am hoping for a one- or two-line solution that I can easily use whenever I make a plot like this.
To make clear what I'm doing in my workaround, I should add an example in linear space (instead of log space):
plot(xdata,ydata)
xmin,xmax = xlim()
xbuff = 0.1*(xmax-xmin)
xlim(xmin-xbuff,xmax+xbuff))
which is identical to the previous example but for a linear axis.
A related problem is that sometimes the limits are too large. Say my data is something like ydata = xdata**0.25
so that the variance in the range is much less than a decade but ends at exactly 10**1
. Then, the autoscale ylim
are 10**0
to 10**1
though the data are only in the top portion of the plot. Using my workaround above, I can increase ymax
so that the third point is fully within the limits but I don't know how to increase ymin
so that there is less whitespace at the lower portion of my plot. i.e., the point is that I don't always want to spread my limits apart but would just like to have some constant (or proportional) buffer around all my points.
ylim( limits ) sets the y-axis limits for the current axes or chart. Specify limits as a two-element vector of the form [ymin ymax] , where ymax is greater than ymin .
The limits on an axis can be set manually (e.g. ax. set_xlim(xmin, xmax) ) or Matplotlib can set them automatically based on the data already on the axes. There are a number of options to this autoscaling behaviour, discussed below.
Show activity on this post. The python plotting library matplotlib will by default add margins to any plot that it generates. They can be reduced to a certain degree through some options of savefig() , namely bbox_inches='tight' and pad_inches=0 .
@askewchan I just succesfully achieved how to change matplotlib settings by editing matplotlibrc configuration file and running python directly from terminal. Don't know the reason yet, but matplotlibrc is not working when I run python from spyder3 (my IDE). Just follow steps here matplotlib.org/users/customizing.html.
1) Solution one (default for all plots)
Try put this in matplotlibrc and you will see the buffer increase:
axes.xmargin : 0.1 # x margin. See `axes.Axes.margins`
axes.ymargin : 0.1 # y margin See `axes.Axes.margins`
Values must be between 0 and 1.
Obs.: Due to bugs, scale is not correctly working yet. It'll be fixed for matplotlib 1.5 (mine is 1.4.3 yet...). More info:
2) Solution two (individually for each plot inside the code)
There is also the margins function (for put directly in the code). Example:
import numpy as np
from matplotlib import pyplot as plt
t = np.linspace(-6,6,1000)
plt.plot(t,np.sin(t))
plt.margins(x=0.1, y=0.1)
plt.savefig('plot.png')
Obs.: Here scale is working (0.1 will increase 10% of buffer before and after x-range and y-range).
A similar question was posed to the matplotlib-users list earlier this year. The most promising solution involves implementing a Locator (based on MaxNLocator in this case) to override MaxNLocator.view_limits.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With