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.