How to add a title and suptitle to each gridspec group

4.9k views Asked by At

I know I can use update to adjust the parameters of a GridSpec instance in a matplotlib figure, allowing to arrange multiple gridspec's in a single figure. Much as in this example taken from the matplotlib doc

gs1 = gridspec.GridSpec(3, 3)
gs1.update(left=0.05, right=0.48, wspace=0.05)
ax1 = plt.subplot(gs1[:-1, :])
ax2 = plt.subplot(gs1[-1, :-1])
ax3 = plt.subplot(gs1[-1, -1])

gs2 = gridspec.GridSpec(3, 3)
gs2.update(left=0.55, right=0.98, hspace=0.05)
ax4 = plt.subplot(gs2[:, :-1])
ax5 = plt.subplot(gs2[:-1, -1])
ax6 = plt.subplot(gs2[-1, -1])

But how can I give both gs1 and gs2 their own common title? Using suptitle I only get a common title for the whole figure at once.

2

There are 2 answers

3
pathoren On

I can think of four ways, all quite ugly. I do not know if there are any automatic way of setting such things.

The four ugly ways are:

1) Set the title to the "top" axis-object in each group with ax.set_title() (in your case ax1 and ax4). It works great on the left group, but horrible for the right group...

2) Set one title with fig.suptitle, but make a lot of spaces inside the title, and use horizontalalignment='center'.

3) Set a text-object manually for each title... (not in the example below, but just look at matplotlib.text)

4) Create ghost axes, hide everything on them and just use them to set their title...

Below is some example code

import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec

fig = plt.figure()
gs1 = gridspec.GridSpec(3, 3)
gs1.update(left=0.05, right=0.48, wspace=0.05)
ax1 = fig.add_subplot(gs1[:-1, :])
ax2 = fig.add_subplot(gs1[-1, :-1])
ax3 = fig.add_subplot(gs1[-1, -1])
ax1.set_title('Left group title')  # Alternative 1)

gs2 = gridspec.GridSpec(3, 3)
gs2.update(left=0.55, right=0.98, hspace=0.05)
ax4 = fig.add_subplot(gs2[:, :-1])
ax5 = fig.add_subplot(gs2[:-1, -1])
ax6 = fig.add_subplot(gs2[-1, -1])
ax4.set_title('Right group title')  # Alternative 1)
# Alternative 2. Note the many white-spaces
fig.suptitle('figure title left                                                   figure title right', horizontalalignment='center')

# Alternative 4)
rect_left = 0, 0, 0.5, 0.8  # lower, left, width, height (I use a lower height than 1.0, to place the title more visible)
rect_right = 0.5, 0, 0.5, 0.8
ax_left = fig.add_axes(rect_left)
ax_right = fig.add_axes(rect_right)
ax_left.set_xticks([])
ax_left.set_yticks([])
ax_left.spines['right'].set_visible(False)
ax_left.spines['top'].set_visible(False)
ax_left.spines['bottom'].set_visible(False)
ax_left.spines['left'].set_visible(False)
ax_left.set_axis_bgcolor('none')
ax_right.set_xticks([])
ax_right.set_yticks([])
ax_right.spines['right'].set_visible(False)
ax_right.spines['top'].set_visible(False)
ax_right.spines['bottom'].set_visible(False)
ax_right.spines['left'].set_visible(False)
ax_right.set_axis_bgcolor('none')
ax_left.set_title('Ghost left title')
ax_right.set_title('Ghost right title')

plt.show()

enter image description here

0
Simon Grosse-Holz On

Way too late, but just found this thread when searching for the exact same thing, so just leaving this for anyone stumbling across it.

I think @pathoren's Alternative 4) is the way to go, but you can reuse the existing gridspec to create your ghost axis such that it exactly matches the existing ones:

import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec

fig = plt.figure()
gs1 = gridspec.GridSpec(3, 3)
gs1.update(left=0.05, right=0.48, wspace=0.05)
ax1 = fig.add_subplot(gs1[:-1, :])
ax2 = fig.add_subplot(gs1[-1, :-1])
ax3 = fig.add_subplot(gs1[-1, -1])

gs2 = gridspec.GridSpec(3, 3)
gs2.update(left=0.55, right=0.98, hspace=0.05)
ax4 = fig.add_subplot(gs2[:, :-1])
ax5 = fig.add_subplot(gs2[:-1, -1])
ax6 = fig.add_subplot(gs2[-1, -1])

# Add ghost axes and titles on gs1 and gs2
ax_left = fig.add_subplot(gs1[:])
ax_left.axis('off')
ax_left.set_title('Left title')

ax_right = fig.add_subplot(gs2[:])
ax_right.axis('off')
ax_right.set_title('Right title')

plt.show()

Resulting layout:

Resulting layout