3
votes

I would like to create a plot with 3 subplots. This plot should have a common y and common x label I followed: Common xlabel/ylabel for matplotlib subplots.

I am however changing the aspect ratio aspect=0.5 and this results in the x-label being too far from the plot. Do you know how to fix this?

enter image description here

> Minimal Reproducible Example here:

import numpy as np
import matplotlib.pyplot as plt

# Get Data 
data1 = np.random.rand(100,100)
data2 = np.random.rand(100,100)
data3 = np.random.rand(100,100)
data = [data1,data2,data3]
# Create Figure
fig, axes = plt.subplots(nrows=1, ncols=3, sharex=True, sharey=True)
for i,ax in enumerate(axes.flat):
    im = ax.imshow(data[i], origin="lower", interpolation='quadric', cmap='jet', extent=[50,250,0,400], aspect=0.5, vmin=0, vmax = 1)


cbar_ax = fig.add_axes([1, 0.35, 0.01, 0.3])
fig.colorbar(im, cax=cbar_ax) # orientation='horizontal'
fig.tight_layout(pad=0.7)

## add a big axis, hide frame
fig.add_subplot(111, frameon=False)
## hide tick and tick label of the big axis
plt.tick_params(labelcolor='none', top=False, bottom=False, left=False, right=False)
plt.xlabel("common X")
plt.ylabel("common Y")


plt.show()
2
There is of course plt.xlabel("common X", labelpad=n), which takes negative n-values - but it is an absolute value. - Mr. T

2 Answers

3
votes

Here is a solution. The idea is to create a big axis with actual extremal positions of the set of subplots. This should be flexible with different subplot settings.

common label row subplots

import numpy as np
import matplotlib.pyplot as plt

# Get Data
data1 = np.random.rand(100,100)
data2 = np.random.rand(100,100)
data3 = np.random.rand(100,100)
data = [data1,data2,data3]
# Create Figure
fig, axes = plt.subplots(nrows=1, ncols=3, sharex=True, sharey=True)
for i,ax in enumerate(axes.flat):
    im = ax.imshow(data[i], origin="lower", interpolation='quadric', cmap='jet', extent=[50,250,0,400], aspect=0.5, vmin=0, vmax = 1)


cbar_ax = fig.add_axes([1, 0.35, 0.01, 0.3])
fig.colorbar(im, cax=cbar_ax) # orientation='horizontal'
fig.tight_layout(pad=1.5)

# Get extents of subplot
x0 = min([ax.get_position().x0 for ax in axes])
y0 = min([ax.get_position().y0 for ax in axes])
x1 = max([ax.get_position().x1 for ax in axes])
y1 = max([ax.get_position().y1 for ax in axes])

# Hidden axes for common x and y labels
plt.axes([x0, y0, x1 - x0, y1 - y0], frameon=False)
plt.tick_params(labelcolor='none', top=False, bottom=False, left=False, right=False)

# Labelize
plt.xlabel("common X")
plt.ylabel("common Y")
plt.title('Common Title')

plt.show()
# plt.savefig("example.png", bbox_inches="tight")  # save figure
1
votes

Since you already defined a subplot, you can set its ratio as well:

## add a big axis, hide frame
allax = fig.add_subplot(111, frameon=False)
allax.set_aspect(.3) #slightly smaller than 1/3 because of the colorbar