253

I would like to limit the X and Y axis in matplotlib for a specific subplot. The subplot figure itself doesn't have any axis property. I want for example to change only the limits for the second plot:

import matplotlib.pyplot as plt
fig=plt.subplot(131)
plt.scatter([1,2],[3,4])
fig=plt.subplot(132)
plt.scatter([10,20],[30,40])
fig=plt.subplot(133)
plt.scatter([15,23],[35,43])
plt.show()
Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
Cupitor
  • 11,007
  • 19
  • 65
  • 91
  • your question was not clear, I can think of may 4 or 5 ways to set up something this simple with sub-plots. – tacaswell Apr 07 '13 at 02:34
  • 2
    If you can think of setting up in 4 or 5 ways, it shows that you already understood the question in the first place. – Cupitor Apr 07 '13 at 02:36
  • 6
    Because, I suspected that you have some gaps in your understanding of the class hierarchy of of mpl (which your variable names confirm). Thus, you will benefit the most if I can show you how to adapt the code you already have. – tacaswell Apr 07 '13 at 02:50

1 Answers1

351

You should use the OO interface to matplotlib, rather than the state machine interface. Almost all of the plt.* function are thin wrappers that basically do gca().*.

plt.subplot returns an axes object. Once you have a reference to the axes object you can plot directly to it, change its limits, etc.

import matplotlib.pyplot as plt

ax1 = plt.subplot(131)
ax1.scatter([1, 2], [3, 4])
ax1.set_xlim([0, 5])
ax1.set_ylim([0, 5])


ax2 = plt.subplot(132)
ax2.scatter([1, 2],[3, 4])
ax2.set_xlim([0, 5])
ax2.set_ylim([0, 5])

and so on for as many axes as you want.

or better, wrap it all up in a loop:

import matplotlib.pyplot as plt

DATA_x = ([1, 2],
          [2, 3],
          [3, 4])

DATA_y = DATA_x[::-1]

XLIMS = [[0, 10]] * 3
YLIMS = [[0, 10]] * 3

for j, (x, y, xlim, ylim) in enumerate(zip(DATA_x, DATA_y, XLIMS, YLIMS)):
    ax = plt.subplot(1, 3, j + 1)
    ax.scatter(x, y)
    ax.set_xlim(xlim)
    ax.set_ylim(ylim)
tacaswell
  • 84,579
  • 22
  • 210
  • 199
  • 2
    Problem with keeping the axis instance is that it does not have all the properties that plt has, for example one cannot use axis.ylim() to get the ylim of the plot on an axis. – dashesy Jan 21 '14 at 19:09
  • 9
    @dashesy You use `set_xlim` and `set_ylim`. `plt` has many _fewer_ options than working directly with the axes object. In fact, almost every function in `plt` is a very thin wrapper that first calls `ax = plt.gca()` and then calls what ever function on that object. You should not be using `plt` for anything but interactive work. – tacaswell Jan 21 '14 at 19:12
  • 1
    Yes, I agree, not relying on the interactive version is preferable, but there is no way to *get* the ylim of a plot having only axis. After a plot is done, it will have an **automatic** ylim assigned, but the axis will not have that information. So if latter drawings depend on the ylim, as you said one has to set_ylim to override the current range. – dashesy Jan 21 '14 at 21:45
  • 13
    sorry, forgot about that bit of magic in `plt.ylim`. There is also a `get_ylim()` function on the `axes` which will return the limits and `ax.get_yaxis()` function which will return to you the `axis` (note difference between `axes` and `axis`). There are also the symmetric versions for the xaxis. – tacaswell Jan 21 '14 at 21:55
  • I'm confused about something, why is that sometimes bare `xlim` and `ylim` do the job and sometimes `set_xlim` and `set_ylim`? – aderchox Apr 01 '20 at 15:08
  • 1
    @aderchox because they are in different namespaces. `plt.xlim` and `plt.ylim` are in `matplotlib.pyplot` and `ax.set_xlim` and `ax.set_ylim` are methods on the `Axes` object. In almost all cases you should prefer to use the Axes methods rather than pyplot. – tacaswell Apr 01 '20 at 16:51
  • @tacaswell Thanks, I checked it now and you're right, but indeed the reason I got confused is that the docs contains something weird. In this page for the `Axes` api (https://matplotlib.org/api/axes_api.html), it says `xlim` and `ylim`, but when you click on them it shows them correctly as `set_xlim` and `set_ylim` as you said. Thanks anyways. – aderchox Apr 01 '20 at 22:04