Welcome back. In our last lesson, you gained hands-on experience creating and customizing line and bar charts using Matplotlib's object-oriented API. You've mastered the foundational workflow of creating a single Figure and Axes with fig, ax = plt.subplots() and then using methods on the ax object to build a complete visualization.
Today, we will expand on that foundation to compose figures with multiple plots. While a single chart is powerful, placing several charts side-by-side in a single figure allows for direct comparison, revealing deeper patterns and telling a more complex story. By the end of this lesson, you will be able to arrange multiple Axes objects into a grid, customize each one individually, and link their axes for clear, effective comparisons.
From One Plot to Many: The Concept of Subplots
So far, we've used plt.subplots() without any arguments, which creates a single Axes within a Figure. The real power of this function is revealed when we provide arguments to create a grid of Axes. Each individual plot area in this grid is called a subplot.
Imagine you want to compare three different aspects of your data. You could create a layout like this:

To build such figures, we simply need to tell plt.subplots() how many rows and columns of Axes we want.
Understanding plt.subplots(nrows, ncols)
The key to creating multi-panel figures lies in the first two arguments of the plt.subplots() function: nrows and ncols.
When you call fig, ax = plt.subplots(nrows=2, ncols=1), for example, Matplotlib understands that you want a figure with two plots stacked vertically. The crucial difference is in what gets returned. Instead of a single ax object, you now get a collection of them.
The following video from Corey Schafer explains this transition clearly. It will show you how the object you use for plotting changes when you request more than one subplot.
Matplotlib Tutorial (Part 10): Subplots
This video segment demonstrates what happens to the ax variable when you ask plt.subplots() for more than one plot.
Please watch from this explanation of creating multiple plots. Pay close attention to how the ax variable, which was previously a single Axes object, becomes a list (or more accurately, a NumPy array) of Axes objects when nrows is greater than one.
As you saw, requesting multiple subplots changes the ax variable into an array of Axes objects.
plt.subplots(2, 1)returns an array of twoAxesobjects.plt.subplots(2, 2)returns a 2x2 array of fourAxesobjects.
To manage these individual Axes, you can either unpack them into separate variables or access them using array indexing.
Populating and Customizing Individual Subplots
Once you have your array of Axes, you can plot on each one just as you did with a single ax object. You simply need to specify which ax you are working on.
Unpacking Axes
For a small number of subplots, unpacking is often the clearest approach. Let's say you want two plots side-by-side:
# Create a figure with 1 row and 2 columns of subplots
fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2)
# Plot on the first axes
ax1.plot(x_data, y_data1)
ax1.set_title("First Plot")
# Plot on the second axes
ax2.plot(x_data, y_data2)
ax2.set_title("Second Plot")
plt.show()
This next video segment demonstrates this exact unpacking technique in a practical example.
Matplotlib Tutorial (Part 10): Subplots
Corey Schafer continues by showing how to unpack the returned axes into distinct variables (ax1, ax2) and then plot different data on each.
Watch from this demonstration. Observe how he calls .plot() and .set_title() on ax1 and ax2 independently to build up the two separate charts.
Accessing Axes by Index
When you have a larger grid (e.g., 2x2 or more), unpacking becomes cumbersome. In this case, it's better to access the Axes using standard 2D array indexing. The returned axs object is a NumPy array, so you can use axs[row, column] to select a specific subplot.
This quick video provides a very direct and fast-paced example of building a 2x2 grid using this indexing method.
Matplotlib subplots in 6 minutes! 🔲
This "Bro Code" video concisely demonstrates the creation of a 2x2 grid and how to access each subplot by its index.
First, watch the brief explanation of the subplots function and the returned objects. Then, focus on the section where individual subplots are populated using 2D indexing, like axes[0, 0] for the top-left plot.
Here's a summary of the indexing approach for a 2x2 grid:
# Create a 2x2 grid of subplots
fig, axs = plt.subplots(nrows=2, ncols=2)
# Top-left plot
axs[0, 0].plot(x, y1)
axs[0, 0].set_title("Top Left")
# Top-right plot
axs[0, 1].plot(x, y2)
axs[0, 1].set_title("Top Right")
# Bottom-left plot
axs[1, 0].plot(x, y3)
axs[1, 0].set_title("Bottom Left")
# Bottom-right plot
axs[1, 1].plot(x, y4)
axs[1, 1].set_title("Bottom Right")
plt.show()
A Key Design Principle: Sharing Axes
One of the primary reasons to use subplots is for comparison. To make comparisons valid and easy for the viewer, it's crucial that the plots share a common scale when appropriate. For example, if you are plotting time-series data for two different categories in vertically stacked subplots, their x-axes (time) should be identical.
Matplotlib makes this easy with the sharex and sharey arguments in plt.subplots().
Setting sharex=True or sharey=True ensures that all subplots in the grid will share the same axis limits, grid lines, and ticks. As a bonus, Matplotlib will automatically remove the tick labels from the inner axes, which helps declutter your figure—a principle we'll explore more in later lessons.
The following documentation provides a perfect visual explanation of this feature.
Create multiple subplots using plt.subplots
This official Matplotlib gallery example clearly illustrates the effect and benefit of sharing axes.
Please navigate to the section "Sharing axes". First, look at the plot under the text "By default, each Axes is scaled individually" to see the problem of unaligned axes. Then, see the immediate improvement in the next plot, created using the sharex parameter. Finally, notice how setting sharex=True and sharey=True automatically removes redundant tick labels for a cleaner look in the plot under "Setting sharex or sharey to True enables global sharing".
As a final touch, titles and labels can sometimes overlap in a dense grid. You can ask Matplotlib to automatically adjust the spacing to prevent this by adding plt.tight_layout() right before plt.show(). This simple command can significantly improve the final appearance of your figure.
Key Takeaways
- You can create a grid of plots (subplots) using
plt.subplots(nrows, ncols). - This function returns a
Figureobject and a NumPy array ofAxesobjects. - You can assign data and customizations to each subplot by either unpacking the
Axesarray into separate variables or by accessing eachAxesobject using 2D indexing (e.g.,axs[0, 1]). - For effective comparison, use the
sharex=Trueandsharey=Truearguments to link the scales of your subplots. This also helps declutter the figure by removing redundant labels.
What's Next?
You now have the technical skills to create both single and multi-panel static charts. This completes the foundational module on the mechanics of Matplotlib.
In our next lesson, we will pivot from the "how" of plotting to the "what" and "why". We'll begin exploring the core principles of effective data visualization, starting with how to map different types of data (like categories or quantities) to the most effective visual properties (like length, position, and color). This will provide the theoretical framework you need to start making informed, effective design choices for your charts.