Skip to content

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