Matplotlib Subplots Function

plt.subplots() creates a figure and a grid of Axes objects together in one call, giving you individual variables to control each plot instead of repeated subplot() calls.

A Cleaner Way to Build Grids

The older plt.subplot() function works fine for a couple of plots, but repeating it for every cell in a larger grid gets verbose, and it does not give you a direct handle to each plot's axes. plt.subplots() (note the 's' — it is a different function) solves this by creating the whole figure and grid of Axes objects in one call and handing them back to you as objects you can act on directly.

Basic Usage

fig, ax = plt.subplots() creates a figure with a single plot area, returning the Figure object and one Axes object. When you ask for a grid, ax becomes a NumPy array of Axes objects instead of a single one.

Example

import matplotlib.pyplot as plt
import numpy as np

x = np.array([0, 1, 2, 3, 4, 5])
y = np.array([0, 1, 4, 9, 16, 25])

fig, ax = plt.subplots()
ax.plot(x, y)
ax.set_title("A single Axes object")
plt.show()
Note: Working with Axes objects means you call ax.plot(), ax.set_title(), ax.set_xlabel(), and so on, instead of the plt. versions. This object-oriented style scales better once a figure has more than one plot.

Creating a Grid of Plots

Pass the number of rows and columns to plt.subplots(nrows, ncols) to build a grid. The returned ax is a 2D NumPy array shaped (nrows, ncols), so you index it like ax[0, 0] for the top-left plot and ax[1, 1] for the plot in the second row, second column.

Example

import matplotlib.pyplot as plt
import numpy as np

months = np.array(["Jan", "Feb", "Mar", "Apr"])
product_a = np.array([120, 135, 150, 170])
product_b = np.array([80, 95, 88, 102])

fig, ax = plt.subplots(2, 2, figsize=(8, 6))

ax[0, 0].plot(months, product_a)
ax[0, 0].set_title("Product A - Line")

ax[0, 1].bar(months, product_a)
ax[0, 1].set_title("Product A - Bar")

ax[1, 0].plot(months, product_b)
ax[1, 0].set_title("Product B - Line")

ax[1, 1].bar(months, product_b)
ax[1, 1].set_title("Product B - Bar")

fig.suptitle("Quarterly comparison")
fig.tight_layout()
plt.show()
Note: When a grid has only one row or one column, such as plt.subplots(1, 3), ax comes back as a plain 1D array, so you index it with a single number like ax[0], ax[1], ax[2] rather than a row and column pair.
  • One function call builds the entire figure and grid, rather than one call per plot.
  • Each Axes object is a named variable you can pass around, store in a list, or loop over.
  • The figsize argument sizes the whole figure once, instead of being set separately for each plot.
  • sharex=True and sharey=True let every plot in the grid share the same axis scale, which keeps comparisons fair.

Example

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)

fig, ax = plt.subplots(1, 2, sharey=True, figsize=(8, 4))
ax[0].plot(x, np.sin(x))
ax[0].set_title("Sine wave")
ax[1].plot(x, np.cos(x))
ax[1].set_title("Cosine wave")
plt.show()

Exercise: Matplotlib Subplots

In plt.subplot(2, 3, index), what do the first two arguments represent?