0

I'm using matplotlib to plot a probability distribution which looks something like the sum of a Pareto distribution and a Gaussian with positive mean. In other words it has very large values near 0, a small local minimum at x = a, a local maximum at x = b > a, and a long right tail decaying to 0. I'd like to set the y limits based only on those values to the right of the local minimum, i.e. cut off the left-most values so as to focus on the local maximum. I know I can do this with:

plt.plot(pdf)
plt.ylim((0, local_maximum))

However, this sets ymax to exactly the value of the local maximum, which makes the plot look ugly for two reasons:

  1. the local maximum touches the top boundary of the plot, with no space above
  2. the y axis is not a round multiple of ytics, so it's not clear what the maximum value is

Matplotlib's algorithm for choosing a default axis is pretty good, so my current hack is to plot twice: the first time I plot only the data above the local minimum for the purpose of choosing a good ylim, and the second time I plot all the data, as follows:

fig, ax = plt.subplots()
# first plot the data above the local minimum x=a, just to get a good ymax
plt.plot(pdf[a:])
ymin, ymax = plt.ylim()
# now plot all the data using the nice ymax
fig.clear()
plt.ylim((0, ymax))
plt.plot(pdf)

This gives me a good ymax that is a round multiple of ytics and fits al the data up to the local maximum, with a bit of whitespace.

Is there a better way, that doesn't require plotting twice?

tmdavison
  • 64,360
  • 12
  • 187
  • 165
Josh Milthorpe
  • 956
  • 1
  • 14
  • 27
  • 1
    Why not add a relative value to your local_maximum? For example: `plt.ylim((0, 1.1*local_maximum))`. Adjust 1.1 accordingly. – Repiklis Sep 21 '16 at 11:59
  • You might want to look at tick frequency: http://stackoverflow.com/questions/12608788/changing-the-tick-frequency-on-x-or-y-axis-in-matplotlib – kezzos Sep 21 '16 at 12:18
  • @Repiklis that solves the first problem (whitespace at the top), but not the second (ymax a round multiple of ytics) – Josh Milthorpe Sep 21 '16 at 12:51
  • You are right! You can round the upper limit to a sensible value (to avoid any weird increments) and then use `ax.yaxis.set_major_locator(matplotlib.ticker.LinearLocator())`. Check [`matplotlib.ticker`](http://matplotlib.org/api/ticker_api.html#matplotlib.ticker.LinearLocator) for more options (`MaxNLocator` is also a good option) and the link by @kezzos for other approaches. – Repiklis Sep 21 '16 at 14:38

0 Answers0