Tight Layout¶
Tight layout automatically adjusts subplot parameters to prevent overlapping labels and titles.
The Problem¶
Without adjustment, labels and titles can overlap.
1. Overlapping Labels¶
import matplotlib.pyplot as plt
import numpy as np
fig, axes = plt.subplots(2, 2, figsize=(8, 6))
for ax in axes.flat:
ax.plot(np.random.randn(100).cumsum())
ax.set_xlabel('Long X-axis Label')
ax.set_ylabel('Long Y-axis Label')
ax.set_title('Title with Some Text')
# Labels may overlap!
plt.show()
2. Crowded Subplots¶
fig, axes = plt.subplots(3, 3, figsize=(8, 8))
for ax in axes.flat:
ax.plot(np.random.randn(50))
ax.set_xlabel('X')
ax.set_ylabel('Y')
# Titles and labels collide
plt.show()
3. Suptitle Overlap¶
fig, axes = plt.subplots(2, 2)
fig.suptitle('Main Title', fontsize=16)
for ax in axes.flat:
ax.set_title('Subplot Title')
# Suptitle overlaps subplot titles
plt.show()
tight_layout Solution¶
Apply automatic spacing adjustment.
1. Basic Usage¶
fig, axes = plt.subplots(2, 2, figsize=(8, 6))
for ax in axes.flat:
ax.plot(np.random.randn(100).cumsum())
ax.set_xlabel('Long X-axis Label')
ax.set_ylabel('Long Y-axis Label')
ax.set_title('Title with Some Text')
fig.tight_layout()
plt.show()
2. Figure Method¶
fig, axes = plt.subplots(2, 2)
# ... configure plots ...
fig.tight_layout()
3. Pyplot Function¶
plt.subplot(2, 2, 1)
plt.plot(np.random.randn(50))
plt.title('Plot 1')
plt.subplot(2, 2, 2)
plt.plot(np.random.randn(50))
plt.title('Plot 2')
plt.tight_layout()
plt.show()
tight_layout Parameters¶
Fine-tune the automatic adjustment.
1. Padding¶
fig, axes = plt.subplots(2, 2)
fig.tight_layout(pad=2.0) # Extra padding around figure edge
plt.show()
2. Subplot Padding¶
fig, axes = plt.subplots(2, 2)
fig.tight_layout(
h_pad=1.0, # Height padding between subplots
w_pad=1.0 # Width padding between subplots
)
plt.show()
3. Parameter Reference¶
fig.tight_layout(
pad=1.08, # Padding between figure edge and subplot edges
h_pad=None, # Height padding between subplots
w_pad=None, # Width padding between subplots
rect=None # Rectangle in figure coords (left, bottom, right, top)
)
rect Parameter¶
Reserve space for figure-level elements.
1. Space for Suptitle¶
fig, axes = plt.subplots(2, 2)
for ax in axes.flat:
ax.plot(np.random.randn(50))
fig.suptitle('Main Title', fontsize=16)
fig.tight_layout(rect=[0, 0, 1, 0.95]) # Leave 5% at top
plt.show()
2. Space for Legend¶
fig, axes = plt.subplots(1, 2)
for ax in axes:
ax.plot(np.random.randn(50), label='Data')
fig.legend(loc='lower center', ncol=2)
fig.tight_layout(rect=[0, 0.1, 1, 1]) # Leave 10% at bottom
plt.show()
3. Custom Margins¶
fig, axes = plt.subplots(2, 2)
fig.tight_layout(rect=[0.05, 0.05, 0.95, 0.95]) # 5% margins all around
plt.show()
constrained_layout¶
Modern alternative to tight_layout.
1. Enable at Creation¶
fig, axes = plt.subplots(2, 2, figsize=(8, 6), constrained_layout=True)
for ax in axes.flat:
ax.plot(np.random.randn(100).cumsum())
ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_title('Title')
# No need to call tight_layout!
plt.show()
2. With Colorbars¶
fig, axes = plt.subplots(1, 2, constrained_layout=True)
im1 = axes[0].imshow(np.random.rand(10, 10))
im2 = axes[1].imshow(np.random.rand(10, 10))
fig.colorbar(im1, ax=axes[0])
fig.colorbar(im2, ax=axes[1])
plt.show()
3. Advantages¶
# constrained_layout handles:
# - Colorbars automatically
# - Legends better
# - More complex layouts
# - Updates dynamically during interactive sessions
subplots_adjust¶
Manual control over spacing.
1. Basic Adjustment¶
fig, axes = plt.subplots(2, 2)
for ax in axes.flat:
ax.plot(np.random.randn(50))
fig.subplots_adjust(
left=0.1,
right=0.95,
bottom=0.1,
top=0.9
)
plt.show()
2. Subplot Spacing¶
fig.subplots_adjust(
wspace=0.4, # Width space between subplots
hspace=0.4 # Height space between subplots
)
3. Full Control¶
fig.subplots_adjust(
left=0.1, # Left margin
right=0.95, # Right margin
bottom=0.1, # Bottom margin
top=0.9, # Top margin
wspace=0.4, # Width space between subplots
hspace=0.4 # Height space between subplots
)
Method Comparison¶
Choose the right approach for your needs.
1. tight_layout¶
# Pros: Simple, usually works
# Cons: May fail with complex layouts, colorbars
# Best for: Quick fixes, simple grids
fig.tight_layout()
2. constrained_layout¶
# Pros: More robust, handles colorbars, dynamic
# Cons: Slightly slower, must set at creation
# Best for: New projects, complex figures
fig, ax = plt.subplots(constrained_layout=True)
3. subplots_adjust¶
# Pros: Full control, precise positioning
# Cons: Manual tuning required
# Best for: Publication figures, exact specifications
fig.subplots_adjust(left=0.15, right=0.85)
Best Practices¶
Guidelines for effective layout management.
1. Order of Operations¶
fig, axes = plt.subplots(2, 2)
# 1. Create plots
for ax in axes.flat:
ax.plot(np.random.randn(50))
# 2. Set labels and titles
for ax in axes.flat:
ax.set_xlabel('X')
ax.set_ylabel('Y')
# 3. Call tight_layout LAST
fig.tight_layout()
plt.show()
2. Suptitle Pattern¶
fig, axes = plt.subplots(2, 2)
fig.suptitle('Figure Title', fontsize=14)
# Always use rect with suptitle
fig.tight_layout(rect=[0, 0, 1, 0.95])
3. Modern Default¶
# For new projects, prefer constrained_layout
fig, axes = plt.subplots(2, 2, constrained_layout=True)