Complex Layouts with GridSpec

GridSpec is a Matplotlib tool that divides a figure into a flexible grid of rows and columns so individual subplots can span multiple cells and have different sizes.

Learn Complex Layouts with GridSpec in our free Matplotlib course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a…

Part of the free Matplotlib course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

In this lesson you'll build irregular dashboards with fig.add_gridspec() , make a panel span a whole row, control width and height ratios, and reach for subplot_mosaic as a modern shortcut.

Start by asking a figure for a grid with fig.add_gridspec(rows, cols) . The returned object behaves like a 2D array: index it to claim cells, then hand the slice to fig.add_subplot() . A single index like gs[0, 0] grabs one cell, while a slice like gs[1, :] grabs the entire bottom row so one wide panel can span it.

What you'll see: three equal-sized charts (a line, bars, and a scatter) across the top, and a single wide line plot stretching the full width underneath — all titled and neatly spaced by constrained_layout.

By default every row and column is equal. Pass width_ratios and height_ratios to make some bands wider or taller. The numbers are relative, so width_ratios=[2, 1] makes the first column twice as wide as the second. This is perfect for a large main chart with a slim companion panel.

What you'll see: a large red parabola dominating the top-left, a slim teal horizontal-bar panel beside it, and a short golden filled strip running the full width along the bottom.

Manually slicing a GridSpec works, but plt.subplot_mosaic() is far more readable. You draw the layout as an ASCII map (or a nested list) where each letter names a panel. Repeating a letter across neighboring cells merges them into one spanning Axes. You get back a dictionary of Axes keyed by those names — no index math required.

What you'll see: a line chart (A) and a pie chart (B) sharing the top row, with a single purple diagonal line (C) spanning the full width below — accessed cleanly by name.

Replace each ___ to make the top plot span the whole top row of a 2x2 grid.

Hint: the column count is 2 , and a colon : means "all columns".

You forgot the layout solver. Add constrained_layout=True to plt.figure() so titles and ticks don't crash into each other.

Your slice references a row or column that the grid doesn't have. A add_gridspec(2, 3) grid only has rows 0–1 and columns 0–2.

A letter that doesn't form a clean rectangle won't merge. Make sure repeated labels sit in a solid block, and use . for intentionally empty cells.

Build a dashboard where a tall "main" panel fills the left two columns of both rows, with two stacked panels on the right.

Lesson complete — you can design any layout you want!

You created grids with fig.add_gridspec() , made panels span rows and columns with slices, tuned sizes with width and height ratios, and built named dashboards with subplot_mosaic under constrained_layout .

🚀 Up next: Colormaps & Normalization — choose the right color scale and map your data onto it.

Practice quiz

What advantage does GridSpec have over plain plt.subplots()?

  • It is faster to render
  • It allows irregular layouts where panels span cells and differ in size
  • It only works in 3D
  • It adds colorbars automatically

Answer: It allows irregular layouts where panels span cells and differ in size. plt.subplots() makes a uniform grid; GridSpec lets panels span cells and have different sizes.

Which call creates a 2-row, 3-column grid on a figure?

  • fig.add_gridspec(2, 3)
  • plt.gridspec(2, 3)
  • fig.grid(2, 3)
  • ax.add_gridspec(2, 3)

Answer: fig.add_gridspec(2, 3). fig.add_gridspec(rows, cols) returns a GridSpec you can slice into.

What does the slice gs[0, :] select?

  • The left column
  • A single top-left cell
  • The entire top row
  • The bottom-right block

Answer: The entire top row. gs[0, :] takes row 0 across all columns — the whole top row.

After slicing a GridSpec, how do you create the Axes?

Pass the GridSpec slice to fig.add_subplot() to build that Axes.

What does width_ratios=[2, 1] do?

  • Makes the first column twice as wide as the second
  • Makes the first column half as wide
  • Sets row heights
  • Sets the DPI

Answer: Makes the first column twice as wide as the second. width_ratios are relative, so [2, 1] makes the first column twice as wide.

Which argument makes the top row twice as tall as the bottom?

  • row_span=2

height_ratios=[2, 1] makes the first row twice as tall as the second.

What is plt.subplot_mosaic() used for?

  • Saving figures
  • Building named, spanning panels from an ASCII map or nested list
  • 3D rendering
  • Animating plots

Answer: Building named, spanning panels from an ASCII map or nested list. subplot_mosaic builds complex layouts from an ASCII map; repeated labels merge into one panel.

In a mosaic string, what does a '.' (dot) mean?

  • A merged panel
  • An empty cell
  • A colorbar
  • A title

Answer: An empty cell. A '.' leaves a cell intentionally empty in the mosaic layout.

What does subplot_mosaic return for accessing panels?

  • A list of lines
  • A dictionary of Axes keyed by name
  • A single Axes
  • A NumPy array of figures

Answer: A dictionary of Axes keyed by name. You get back a dict of Axes keyed by the labels, e.g. axd['C'].

Which option keeps titles and labels from overlapping with spanning panels?

  • constrained_layout=True
  • overlap=False
  • tidy=True
  • spacing='auto'

Answer: constrained_layout=True. constrained_layout=True runs a solver that keeps labels and titles from colliding.