Subplots with common x and y labels and a common legend under the x-axis

Question:

I am trying to plot a subplot with a common legend displayed at the bottom of the figure below a common x axis label, and with a common y-axis label. I have two ways of almost getting it working, except the first has the common y-axis label overlapping the axis tick labels, while with the second I can’t figure out how to get the legend to show on the plot (it hangs off the page).

Option 2, using the newer supx/ylabel, puts too much space between the subplots and the labels as well – but I think that is fixable (quite a few questions on that one).

These are just example plots, actual plots use more decimals places in the labels, so the overlap is considerable. I will likely also be setting the figure sizes to print (and save) the plots was well.

Plots showing two options given by code below

MWE

import numpy as np
import matplotlib.pyplot as plt

# Some points to plot
x = np.linspace(0, 2 * np.pi, 400)
y = np.sin(x ** 2)
z = np.sin((1.03* x) ** 2)

#option 1 - problem is with my real data the common y label is over the labels of the left hand plot

fig, axs = plt.subplots(2, 2)
axs[0, 0].plot(x, y)
axs[0, 0].plot(x, z, '--')
axs[0, 1].plot(x, y)
axs[0, 1].plot(x, z, '--')
axs[1, 0].plot(x, -y)
axs[1, 0].plot(x, -z, '--')
axs[1, 1].plot(x, -y)
axs[1, 1].plot(x, -z, '--')

fig.add_subplot(111, frameon=False)
plt.tick_params(labelcolor='none', which='both', top=False, bottom=False, left=False, right=False)
plt.xlabel("The X label")
plt.ylabel("The Y label")

fig.subplots_adjust(bottom=0.2)
labels = ["A","B"]
fig.legend(labels,loc='lower center', ncol=len(labels), bbox_to_anchor=(0.55, 0))
fig.tight_layout()


# Option 2 - problem is I can't get the legend to show (it is off the page)
fig, axs = plt.subplots(2, 2)
axs[0, 0].plot(x, y)
axs[0, 0].plot(x, z, '--')
axs[0, 1].plot(x, y)
axs[0, 1].plot(x, z, '--')
axs[1, 0].plot(x, -y)
axs[1, 0].plot(x, -z, '--')
axs[1, 1].plot(x, -y)
axs[1, 1].plot(x, -z, '--')


fig.supxlabel("The X label")
fig.supylabel("The Y label")

fig.subplots_adjust(bottom=0.2)
labels = ["A","B"]
fig.legend(labels,loc='lower center', ncol=len(labels), bbox_to_anchor=(0.55, 0))
fig.tight_layout()
Asked By: Esme_

||

Answers:

You were almost there with your first option, adding labelpad to the ax.set_xlabel() and ax.set_ylabel() calls should fix your issue.

Here is an updated version.

# [...]

fig, axs = plt.subplots(2, 2, figsize=(16, 8), tight_layout=True)

# [...]

# Create the new axis for marginal X and Y labels
ax = fig.add_subplot(111, frameon=False)

# Disable ticks. using ax.tick_params() works as well
ax.set_xticks([])  
ax.set_yticks([])

# Set X and Y label. Add labelpad so that the text does not overlap the ticks
ax.set_xlabel("The X label", labelpad=20, fontsize=12)
ax.set_ylabel("The Y label", labelpad=40, fontsize=12)

# Set fig legend as you did
labels = ["A","B"]
fig.legend(labels, loc='lower center', ncol=len(labels), bbox_to_anchor=(0.55, 0))

enter image description here

Answered By: thmslmr
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.