72

I am having a big plot where I initiated with:

import numpy as np
import matplotlib.pyplot as plt

fig, axs = plt.subplots(5, 4)

And I want to do share-x-axis between column 1 and 2; and do the same between column 3 and 4. However, column 1 and 2 does not share the same axis with column 3 and 4.

I was wondering that would there be anyway to do this, and not sharex=True and sharey=True across all figures?

PS: This tutorial does not help too much, because it is only about sharing x/y within each row/column; they cannot do axis sharing between different rows/columns (unless share them across all axes).

Yuxiang Wang
  • 8,095
  • 13
  • 64
  • 95

4 Answers4

72

I'm not exactly sure what you want to achieve from your question. However, you can specify per subplot which axis it should share with which subplot when adding a subplot to your figure.

This can be done via:

import matplotlib.pylab as plt

fig = plt.figure()

ax1 = fig.add_subplot(5, 4, 1)
ax2 = fig.add_subplot(5, 4, 2, sharex = ax1)
ax3 = fig.add_subplot(5, 4, 3, sharex = ax1, sharey = ax1)
starball
  • 20,030
  • 7
  • 43
  • 238
The Dude
  • 3,795
  • 5
  • 29
  • 47
  • 1
    Thank you! That really helps. I looked and it does not seem that there is a method of the axes object that can set the sharex/sharey property. Do you think that's the case? – Yuxiang Wang May 08 '14 at 00:10
  • I haven't been able to find something so I assume so. I do need to note that my search skills are good but not the best. – The Dude May 09 '14 at 07:54
  • 2
    How does it work with axis arrays does ax[1,0] = plot(x,y) ax[1,1] = plot(x,y,sharey=ax[1,0]) . This does not work – AAI Sep 08 '17 at 16:36
  • 1
    That should be the accepted answer. Don't understand why it is so far down the list. (I guess because it is sorted by Active first). – Fabian Ying Oct 01 '20 at 08:12
  • It works for axis arrays too - make sure you use `np.empty()` for the array, e.g.: ax = np.empty((4, 2), dtype=object); fig = plt.figure(); ax[0][0] = fig.add_subplot(4, 2, 1, sharex=ax[0][0]); ax[0][1] = fig.add_subplot(4, 2, 2, sharex=ax[0][0]) – Balint Pato Apr 04 '23 at 17:08
64

A slightly limited but much simpler option is available for subplots. The limitation is there for a complete row or column of subplots. For example, if one wants to have common y axis for all the subplots but common x axis only for individual columns in a 3x2 subplot, one could specify it as:

import matplotlib.pyplot as plt
fig, ax = plt.subplots(3, 2, sharey=True, sharex='col')
Vinod Kumar
  • 1,383
  • 1
  • 12
  • 26
17

One can manually manage axes sharing using a Grouper object, which can be accessed via ax._shared_x_axes and ax._shared_y_axes. For example,

import matplotlib.pyplot as plt

def set_share_axes(axs, target=None, sharex=False, sharey=False):
    if target is None:
        target = axs.flat[0]
    # Manage share using grouper objects
    for ax in axs.flat:
        if sharex:
            target._shared_x_axes.join(target, ax)
        if sharey:
            target._shared_y_axes.join(target, ax)
    # Turn off x tick labels and offset text for all but the bottom row
    if sharex and axs.ndim > 1:
        for ax in axs[:-1,:].flat:
            ax.xaxis.set_tick_params(which='both', labelbottom=False, labeltop=False)
            ax.xaxis.offsetText.set_visible(False)
    # Turn off y tick labels and offset text for all but the left most column
    if sharey and axs.ndim > 1:
        for ax in axs[:,1:].flat:
            ax.yaxis.set_tick_params(which='both', labelleft=False, labelright=False)
            ax.yaxis.offsetText.set_visible(False)

fig, axs = plt.subplots(5, 4)
set_share_axes(axs[:,:2], sharex=True)
set_share_axes(axs[:,2:], sharex=True)

To adjust the spacing between subplots in a grouped manner, please refer to this question.

herrlich10
  • 6,212
  • 5
  • 31
  • 35
  • Not directly applicable at my use case (sharing x-axis between row 2n and row 2n+1, and sharing y-axis of all even-numbered rows on the one hand, and all odd-numbered rows on the other hand, for an 8 rows by 2 columns figure), but I could adapt it. I didn't know of `Grouper`, nice! – Aubergine Oct 20 '21 at 03:34
  • 1
    The Matplotlib API has been updated, see [this link](https://github.com/matplotlib/matplotlib/blob/710fce3df95e22701bd68bf6af2c8adbc9d67a79/lib/matplotlib/axes/_base.py#L4747-L4749). As a result, you need to change the `if sharex` content to `target._shared_axes['x'].join(target, ax)` and `if sharey` to `target._shared_axes['y'].join(target, ax)`. Then it works for later Matplotlib versions (tested on Matplotlib==3.5.1) – Jonvdrdo Jan 18 '22 at 15:10
3

I used Axes.sharex /sharey in a similar setting

https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.sharex.html#matplotlib.axes.Axes.sharex

import matplotlib.pyplot as plt
fig, axd = plt.subplot_mosaic([list(range(3))] +[['A']*3, ['B']*3])

axd[0].plot([0,0.2])
axd['A'].plot([1,2,3])
axd['B'].plot([1,2,3,4,5])


axd['B'].sharex(axd['A'])

for i in [1,2]:
    axd[i].sharey(axd[0])
plt.show()
tePer
  • 301
  • 2
  • 6