add_subplot vs subplots¶
Overview¶
Matplotlib provides two main ways to create axes within a figure:
| Method | Style | Returns |
|---|---|---|
fig.add_subplot() |
OOP, incremental | Single Axes |
plt.subplots() |
Convenience function | Figure + Axes array |
plt.subplots()¶
Basic Usage¶
Creates figure and all axes at once:
import matplotlib.pyplot as plt
# Single axes
fig, ax = plt.subplots()
ax.plot([1, 2, 3])
# Multiple axes (2 rows, 3 cols)
fig, axes = plt.subplots(2, 3, figsize=(12, 8))
Return Value¶
# 1x1: ax is single Axes object
fig, ax = plt.subplots()
# 1xN or Nx1: axes is 1D array
fig, axes = plt.subplots(1, 3) # shape: (3,)
fig, axes = plt.subplots(3, 1) # shape: (3,)
# NxM: axes is 2D array
fig, axes = plt.subplots(2, 3) # shape: (2, 3)
Accessing Axes¶
fig, axes = plt.subplots(2, 3)
# 2D indexing
axes[0, 0].plot(...) # Top-left
axes[1, 2].plot(...) # Bottom-right
# Flatten for iteration
for ax in axes.flat:
ax.grid(True)
# Unpack if known size
fig, (ax1, ax2) = plt.subplots(1, 2)
fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2)
Common Parameters¶
fig, axes = plt.subplots(
nrows=2,
ncols=3,
figsize=(12, 8),
sharex=True, # Share x-axis
sharey=True, # Share y-axis
squeeze=False, # Always return 2D array
gridspec_kw={'hspace': 0.3, 'wspace': 0.2}
)
fig.add_subplot()¶
Basic Usage¶
Adds one axes at a time to an existing figure:
fig = plt.figure(figsize=(12, 8))
# Add subplot at position (row, col, index) - 1-indexed
ax1 = fig.add_subplot(2, 3, 1) # Row 1, Col 1
ax2 = fig.add_subplot(2, 3, 2) # Row 1, Col 2
ax3 = fig.add_subplot(2, 3, 4) # Row 2, Col 1
Compact Notation¶
# Three-digit shorthand (only for grids < 10x10)
ax1 = fig.add_subplot(231) # Same as (2, 3, 1)
ax2 = fig.add_subplot(232) # Same as (2, 3, 2)
Non-Uniform Grids¶
fig = plt.figure(figsize=(10, 8))
# Large subplot spanning multiple positions
ax1 = fig.add_subplot(2, 2, 1) # Top-left quarter
ax2 = fig.add_subplot(2, 2, 2) # Top-right quarter
ax3 = fig.add_subplot(2, 1, 2) # Bottom half (spans both columns)
With GridSpec¶
from matplotlib.gridspec import GridSpec
fig = plt.figure(figsize=(10, 8))
gs = GridSpec(3, 3, figure=fig)
ax1 = fig.add_subplot(gs[0, :]) # Top row, all columns
ax2 = fig.add_subplot(gs[1:, 0]) # Left column, rows 1-2
ax3 = fig.add_subplot(gs[1:, 1:]) # Bottom-right 2x2
Comparison¶
When to Use plt.subplots()¶
✅ Use when: - Creating regular grid of subplots - All subplots needed at once - Want shared axes - Simple layouts
# Perfect for regular grids
fig, axes = plt.subplots(2, 3)
for ax, data in zip(axes.flat, datasets):
ax.plot(data)
When to Use fig.add_subplot()¶
✅ Use when: - Non-uniform subplot sizes - Adding subplots incrementally - Complex layouts with GridSpec - Mixing different subplot sizes
# Perfect for irregular layouts
fig = plt.figure()
ax_main = fig.add_subplot(2, 2, (1, 2)) # Top half
ax_left = fig.add_subplot(2, 2, 3) # Bottom-left
ax_right = fig.add_subplot(2, 2, 4) # Bottom-right
Side-by-Side Examples¶
Regular 2x2 Grid¶
# plt.subplots (preferred)
fig, axes = plt.subplots(2, 2, figsize=(10, 8))
axes[0, 0].plot(x, y1)
axes[0, 1].plot(x, y2)
axes[1, 0].plot(x, y3)
axes[1, 1].plot(x, y4)
# fig.add_subplot
fig = plt.figure(figsize=(10, 8))
ax1 = fig.add_subplot(221)
ax2 = fig.add_subplot(222)
ax3 = fig.add_subplot(223)
ax4 = fig.add_subplot(224)
ax1.plot(x, y1)
ax2.plot(x, y2)
ax3.plot(x, y3)
ax4.plot(x, y4)
Main Plot with Side Plots¶
# Using add_subplot with GridSpec
fig = plt.figure(figsize=(10, 8))
gs = GridSpec(2, 2, width_ratios=[3, 1], height_ratios=[1, 3])
ax_main = fig.add_subplot(gs[1, 0]) # Main scatter plot
ax_top = fig.add_subplot(gs[0, 0]) # Top histogram
ax_right = fig.add_subplot(gs[1, 1]) # Right histogram
ax_main.scatter(x, y)
ax_top.hist(x, bins=30)
ax_right.hist(y, bins=30, orientation='horizontal')
Common Patterns¶
Iterate Over Subplots¶
# With subplots
fig, axes = plt.subplots(2, 3)
for ax, (title, data) in zip(axes.flat, datasets.items()):
ax.plot(data)
ax.set_title(title)
# With add_subplot
fig = plt.figure()
for i, (title, data) in enumerate(datasets.items(), 1):
ax = fig.add_subplot(2, 3, i)
ax.plot(data)
ax.set_title(title)
Shared Axes¶
# Easy with subplots
fig, axes = plt.subplots(2, 2, sharex=True, sharey=True)
# Manual with add_subplot
fig = plt.figure()
ax1 = fig.add_subplot(221)
ax2 = fig.add_subplot(222, sharex=ax1, sharey=ax1)
ax3 = fig.add_subplot(223, sharex=ax1, sharey=ax1)
ax4 = fig.add_subplot(224, sharex=ax1, sharey=ax1)
Summary¶
| Feature | plt.subplots() |
fig.add_subplot() |
|---|---|---|
| Create multiple at once | ✅ Yes | ❌ One at a time |
| Regular grids | ✅ Ideal | Works |
| Irregular layouts | Limited | ✅ Ideal |
| Shared axes | ✅ Easy (sharex, sharey) |
Manual |
| Return value | Figure + Axes array | Single Axes |
| GridSpec integration | Via gridspec_kw |
✅ Direct |
Recommendation:
- Start with
plt.subplots()for most cases - Use
fig.add_subplot()+ GridSpec for complex layouts