Matplotlib tight_layout() doesn't take into account figure suptitle Matplotlib tight_layout() doesn't take into account figure suptitle python python

Matplotlib tight_layout() doesn't take into account figure suptitle

You can adjust the subplot geometry in the very tight_layout call as follows:

fig.tight_layout(rect=[0, 0.03, 1, 0.95])

As it's stated in the documentation (

tight_layout() only considers ticklabels, axis labels, and titles. Thus, other artists may be clipped and also may overlap.

You could manually adjust the spacing using plt.subplots_adjust(top=0.85):

import numpy as npimport matplotlib.pyplot as pltf = np.random.random(100)g = np.random.random(100)fig = plt.figure()fig.suptitle('Long Suptitle', fontsize=24)plt.subplot(121)plt.plot(f)plt.title('Very Long Title 1', fontsize=20)plt.subplot(122)plt.plot(g)plt.title('Very Long Title 2', fontsize=20)plt.subplots_adjust(top=0.85)

One thing you could change in your code very easily is the fontsize you are using for the titles. However, I am going to assume that you don't just want to do that!

Some alternatives to using fig.subplots_adjust(top=0.85):

Usually tight_layout() does a pretty good job at positioning everything in good locations so that they don't overlap. The reason tight_layout() doesn't help in this case is because tight_layout() does not take fig.suptitle() into account. There is an open issue about this on GitHub: [closed in 2014 due to requiring a full geometry manager - shifted to ].

If you read the thread, there is a solution to your problem involving GridSpec. The key is to leave some space at the top of the figure when calling tight_layout, using the rect kwarg. For your problem, the code becomes:

Using GridSpec

import numpy as npimport matplotlib.pyplot as pltimport matplotlib.gridspec as gridspecf = np.random.random(100)g = np.random.random(100)fig = plt.figure(1)gs1 = gridspec.GridSpec(1, 2)ax_list = [fig.add_subplot(ss) for ss in gs1]ax_list[0].plot(f)ax_list[0].set_title('Very Long Title 1', fontsize=20)ax_list[1].plot(g)ax_list[1].set_title('Very Long Title 2', fontsize=20)fig.suptitle('Long Suptitle', fontsize=24)    gs1.tight_layout(fig, rect=[0, 0.03, 1, 0.95])

The result:

using gridspec

Maybe GridSpec is a bit overkill for you, or your real problem will involve many more subplots on a much larger canvas, or other complications. A simple hack is to just use annotate() and lock the coordinates to the 'figure fraction' to imitate a suptitle. You may need to make some finer adjustments once you take a look at the output, though. Note that this second solution does not use tight_layout().

Simpler solution (though may need to be fine-tuned)

fig = plt.figure(2)ax1 = plt.subplot(121)ax1.plot(f)ax1.set_title('Very Long Title 1', fontsize=20)ax2 = plt.subplot(122)ax2.plot(g)ax2.set_title('Very Long Title 2', fontsize=20)# fig.suptitle('Long Suptitle', fontsize=24)# Instead, do a hack by annotating the first axes with the desired # string and set the positioning to 'figure fraction'.fig.get_axes()[0].annotate('Long Suptitle', (0.5, 0.95),                             xycoords='figure fraction', ha='center',                             fontsize=24                            )

The result:


[Using Python 2.7.3 (64-bit) and matplotlib 1.2.0]