Yuxiang Wang
Yuxiang Wang

Reputation: 8423

Share axes in matplotlib for only part of the subplots

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).

Upvotes: 79

Views: 50749

Answers (4)

herrlich10
herrlich10

Reputation: 6470

One can manually manage axes sharing using a Grouper object, which can be accessed via ax._shared_axes['x'] and ax._shared_axes['y']. 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_axes['x'].join(target, ax)
        if sharey:
            target._shared_axes['y'].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.

EDIT: Modified the code according to the latest matplotlib API updates. Thanks to @Jonvdrdo 's suggestions!

Upvotes: 20

The Dude
The Dude

Reputation: 4005

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)

Upvotes: 77

tePer
tePer

Reputation: 351

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()

Upvotes: 8

Vinod Kumar
Vinod Kumar

Reputation: 1622

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')

Upvotes: 80

Related Questions