Pygmalion
Pygmalion

Reputation: 919

Matplotlib - change automatic axis range

I use automatic axes range for data.

For example, when I use x data between -29 and +31 and I do

ax = plt.gca()
xsta, xend = ax.get_xlim()

I get -30 and 40, which does not appropriately describe data range. I would like see that axes ranges are rounded to 5, i.e. -30 and 35 for limits.

Is it possible to do that? Or, alternatively, is it possible to get exact ranges of x-axes data (-29,31) and then write an algorithm to change that manually (using set_xlim)?

Thanks for help.

Upvotes: 5

Views: 18831

Answers (3)

Joe Kington
Joe Kington

Reputation: 284920

First off, let's set up a simple example:

import matplotlib.pyplot as plt

fig, ax = plt.subplots()
ax.plot([-29, 31], [-29, 31])
plt.show()

enter image description here

If you'd like to know the data range for manually specifying things as you mentioned, you can use:

ax.xaxis.get_data_interval()
ax.yaxis.get_data_interval()

However, it's very common to want to change to a simple padding of the data limits. In that case, use ax.margins(some_percentage). For example, this would pad the limits with 5% of the data range:

import matplotlib.pyplot as plt

fig, ax = plt.subplots()
ax.plot([-29, 31], [-29, 31])
ax.margins(0.05)
plt.show()

enter image description here

To go back to your original scenario, you could manually make the axes limits only use multiples of 5 (but not change the ticks, etc):

import numpy as np
import matplotlib.pyplot as plt

fig, ax = plt.subplots()
ax.plot([-29, 31], [-29, 31])

multiplier = 5.0
for axis, setter in [(ax.xaxis, ax.set_xlim), (ax.yaxis, ax.set_ylim)]:
    vmin, vmax = axis.get_data_interval()
    vmin = multiplier * np.floor(vmin / multiplier)
    vmax = multiplier * np.ceil(vmax / multiplier)
    setter([vmin, vmax])

plt.show()

enter image description here

We could also accomplish the same thing by subclassing the locator for each axis:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import AutoLocator

class MyLocator(AutoLocator):
    def view_limits(self, vmin, vmax):
        multiplier = 5.0
        vmin = multiplier * np.floor(vmin / multiplier)
        vmax = multiplier * np.ceil(vmax / multiplier)
        return vmin, vmax

fig, ax = plt.subplots()
ax.plot([-29, 31], [-29, 31])

ax.xaxis.set_major_locator(MyLocator())
ax.yaxis.set_major_locator(MyLocator())
ax.autoscale()

plt.show()

Upvotes: 12

Karl der Kaefer
Karl der Kaefer

Reputation: 718

When you know you want it in multiples of 5, modify the limits according to the x-range of your data:

import math
import matplotlib.pyplot as pet
#your plotting here
xmin = min( <data_x> )
xmax = max( <data_x> ) 
ax = plt.gca()
ax.set_xlim( [5*math.floor(xmin/5.0), 5*math.ceil(xmax/5.0)]  )

Note that the division has to be by the float 5.0, as int/int neglects the fractional part. For example xmax=6 in 5*math.ceil(6/5) would return 5, which cuts off your data, whereas 5*math.ceil(6/5.0) gives the desired 5*math.ceil(1.2) = 5*2 =10.

Upvotes: 0

elsherbini
elsherbini

Reputation: 1626

To set the axis xlim to the exact range of the data, use the ax.xlim() method in combination with the built in min() and max() functions:

#x could be a list like [0,3,5,6,15]
ax = plt.gca()
ax.xlim([min(x), max(x)]) # evaluates to ax.xlim([0, 15]) with example data above

Upvotes: 0

Related Questions