0Pricing
Pandas & NumPy Academy · Lesson

Figure and Axes Architecture

Understand the Figure-Axes-Artist hierarchy, create plots with plt.subplots(), and differentiate the stateless and object-oriented APIs.

Figure and Axes Architecture is a free Pandas & NumPy Academy lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Pandas & NumPy Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Why Learn Matplotlib Architecture?

Pandas and Seaborn both use Matplotlib internally. Understanding Matplotlib's object hierarchy lets you control every aspect of a plot — from the overall canvas to individual tick marks — and lets you combine multiple charts in a single figure. Without understanding the Figure-Axes model, customising plots quickly becomes a frustrating exercise in guessing which function to call.

The Figure: The Canvas

A Figure is the outermost container — the entire window or image file. It holds one or more Axes objects (the actual plot areas), plus a title, shared legends, and whitespace. You create a Figure with plt.figure() or implicitly through plt.subplots(). Most properties set on the Figure affect the whole canvas: size, background colour, overall title.

import matplotlib.pyplot as plt
import numpy as np

# Create a Figure with a specific size
fig = plt.figure(figsize=(8, 4))  # width=8 inches, height=4 inches
print(type(fig))  # matplotlib.figure.Figure
print('Figure size:', fig.get_size_inches())
plt.close()  # close to avoid display in scripts

The Axes: Where Plotting Happens

An Axes object is a single plot area within a Figure. It contains the x-axis, y-axis, tick marks, grid lines, and all the visual elements (lines, bars, scatter points). Most plotting calls are methods on an Axes object: ax.plot(), ax.bar(), ax.scatter(). One Figure can contain multiple Axes, arranged as a grid of subplots.

fig, ax = plt.subplots()  # Creates Figure + one Axes
print(type(ax))  # matplotlib.axes.Axes

x = np.linspace(0, 10, 100)
ax.plot(x, np.sin(x))  # plot on the Axes
plt.tight_layout()
# plt.show()
plt.close()

plt.subplots(): Create Figure and Axes Together

plt.subplots(nrows, ncols) is the recommended way to create a Figure with one or more Axes in a grid layout. It returns a tuple of (fig, ax) (or (fig, axes_array) for multiple subplots). The figsize parameter sets the total canvas size in inches. Always unpack the result into named variables for clarity.

# Single plot
fig, ax = plt.subplots(figsize=(6, 4))

# 2 rows, 1 column
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(6, 8))

# 2 rows, 2 columns
fig, axes = plt.subplots(2, 2, figsize=(10, 8))
ax_top_left = axes[0, 0]
ax_top_right = axes[0, 1]
print('axes shape:', axes.shape)  # (2, 2)
plt.close('all')

Object-Oriented vs Stateful API

Matplotlib has two usage styles. The stateful (pyplot) API uses plt.plot(), plt.xlabel() etc. and acts on the 'current' axes — convenient for quick interactive exploration. The object-oriented (OO) API explicitly calls methods on ax objects: ax.plot(), ax.set_xlabel(). The OO API is strongly preferred for production code and multi-panel figures because it is unambiguous about which axes is being modified.

x = [1, 2, 3, 4]
y = [1, 4, 9, 16]

# Stateful API (convenient but fragile)
# plt.plot(x, y)
# plt.xlabel('x')
# plt.title('Squares')

# Object-oriented API (preferred)
fig, ax = plt.subplots()
ax.plot(x, y)
ax.set_xlabel('x')
ax.set_title('Squares')
plt.close()

Artists: The Building Blocks

Everything visible in a Matplotlib plot is an Artist: the Figure, Axes, lines, text, patches (rectangles for bars), markers. The Figure-Axes-Artist hierarchy flows from the outermost container down to the smallest visual element. Understanding this hierarchy helps you locate and modify any element programmatically — for example, changing the colour of a specific bar after the chart is drawn.

fig, ax = plt.subplots()
line, = ax.plot([1, 2, 3], [1, 4, 9], color='blue', linewidth=2)

# Introspect the hierarchy
print('Figure:', type(fig))
print('Axes:', type(ax))
print('Line Artist:', type(line))
print('Line color:', line.get_color())
plt.close()

Axis Objects: XAxis and YAxis

Each Axes contains two Axis objects (not to be confused with Axes): ax.xaxis and ax.yaxis. These control ticks, tick labels, and the spine (the visible line). You can set axis limits with ax.set_xlim() and ax.set_ylim(), control tick frequency with ax.set_xticks(), and format labels with ax.xaxis.set_major_formatter().

fig, ax = plt.subplots()
ax.plot([1, 2, 3, 4], [10, 40, 30, 70])

ax.set_xlim(0, 5)
ax.set_ylim(0, 80)
ax.set_xticks([1, 2, 3, 4])
ax.set_xticklabels(['Q1', 'Q2', 'Q3', 'Q4'])
ax.set_xlabel('Quarter')
ax.set_ylabel('Revenue')
plt.close()

Shared Axes for Multi-Panel Plots

When creating a grid of subplots, pass sharex=True or sharey=True to plt.subplots() to link the axis scales across panels. This means zooming or panning one subplot automatically updates all panels sharing that axis — essential for comparing time series across multiple groups where the same x-axis range should be shown in every panel.

import numpy as np

x = np.arange(10)
fig, (ax1, ax2) = plt.subplots(2, 1, sharex=True, figsize=(6, 5))

ax1.plot(x, x**2, color='blue')
ax1.set_title('Squares')

ax2.plot(x, x**3, color='red')
ax2.set_title('Cubes')

fig.suptitle('Powers of x')  # shared figure title
plt.tight_layout()
plt.close()

Spacing with tight_layout()

plt.tight_layout() (or fig.tight_layout()) automatically adjusts subplot parameters to minimise overlap between labels, titles, and tick marks. Call it just before plt.show() or fig.savefig(). For fine-grained control, use plt.subplots_adjust(hspace=, wspace=) to set the vertical and horizontal space between subplots manually.

fig, axes = plt.subplots(2, 2, figsize=(10, 8))

for i, ax in enumerate(axes.flat):
    ax.plot([1, 2, 3], [i, i+1, i+2])
    ax.set_title(f'Panel {i+1}')
    ax.set_xlabel('x axis label')
    ax.set_ylabel('y axis label')

fig.suptitle('Grid of Plots', y=1.02)
plt.tight_layout()  # prevents overlapping labels
plt.close()

Accessing Axes from subplots()

When plt.subplots(nrows, ncols) returns multiple axes, they are packaged in a NumPy array with shape (nrows, ncols). Index them as you would any 2D array: axes[0, 1] for the first row, second column. Use axes.flat to iterate over all axes in row-major order regardless of the grid shape — very convenient for applying the same formatting to every panel.

fig, axes = plt.subplots(2, 3, figsize=(12, 6))

# Access by row, column
axes[0, 0].set_title('Top Left')
axes[1, 2].set_title('Bottom Right')

# Iterate over all axes
for ax in axes.flat:
    ax.set_xlabel('Time')
    ax.set_ylabel('Value')

plt.tight_layout()
plt.close()

Removing Unused Axes

When you create a grid of subplots but do not use every panel, the empty axes still show frame borders. Call ax.set_visible(False) or fig.delaxes(ax) to hide or remove unused axes. A common pattern is to iterate over axes.flat and hide all panels beyond the number of data series you are plotting, keeping the figure clean.

fig, axes = plt.subplots(2, 3, figsize=(12, 6))
data_panels = 4  # only 4 plots needed in a 2x3 grid

for i, ax in enumerate(axes.flat):
    if i < data_panels:
        ax.plot([1, 2, 3], [i, i+1, i+2])
        ax.set_title(f'Panel {i+1}')
    else:
        ax.set_visible(False)  # hide extra panels

plt.tight_layout()
plt.close()

Quick Check

Test your understanding of Matplotlib's Figure and Axes architecture from this lesson.

Lesson Recap

In this lesson you learned: the Figure is the entire canvas and the Axes is a single plot area within it; plt.subplots() creates both together and returns (fig, ax); the object-oriented API (ax.plot(), ax.set_xlabel()) is preferred over the stateful pyplot API; and tight_layout() prevents overlapping labels in multi-panel figures. Next up we create line plots and scatter plots with full control over style.

Frequently asked questions

Is the “Figure and Axes Architecture” lesson free?

Yes — the full text of “Figure and Axes Architecture” is free to read here on the web, and the Pandas & NumPy Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Pandas & NumPy Academy course, upgrade to CoddyKit PRO.

What will I learn in “Figure and Axes Architecture”?

Understand the Figure-Axes-Artist hierarchy, create plots with plt.subplots(), and differentiate the stateless and object-oriented APIs. You practise Pandas & NumPy Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Pandas & NumPy Academy?

No prior experience is required. Pandas & NumPy Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Figure and Axes Architecture” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Pandas & NumPy Academy lesson?

Yes. Every Pandas & NumPy Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Figure and Axes Architecture
  2. Line and Scatter Plots
  3. Bar Charts and Histograms
  4. Labels, Titles, and Saving Figures
← Back to Pandas & NumPy Academy