Back to catalog
Season 36 5 Episodes 18 min 2026

Matplotlib

v3.10 — 2026 Edition. A comprehensive audio course on Matplotlib, Python's most popular visualization library. Learn the core identity, lifecycle of a plot, advanced layouts, plot types, and power-user workflows for version 3.10.

Data Visualization Data Science
Matplotlib
Now Playing
Click play to start
0:00
0:00
1
The Core Identity: Figures, Axes, and Interfaces
Welcome to Matplotlib. In this episode, we define the mental model at the heart of Python's most popular visualization library. Learn the difference between a Figure and an Axes, and why the explicit Object-Oriented interface is your best tool.
3m 27s
2
The Lifecycle of a Plot
Discover how to take a plot from raw data to a labeled, formatted display. We walk through the lifecycle of a simple chart, showing you exactly how to add labels, titles, and custom tick formatters using the explicit interface.
3m 25s
3
Mastering Layouts: Subplots and Mosaics
Learn how to manage multiple plots on a single canvas without them overlapping. This episode covers plt.subplots, the power of subplot_mosaic for semantic layouts, and using constrained layout to keep things tidy.
3m 47s
4
Beyond the Line: Exploring Core Plot Types
Move beyond basic lines and scatter plots. We map out Matplotlib's plot categories, contrasting statistical distribution plots with gridded data functions like imshow and pcolormesh.
3m 43s
5
Power-User Workflows: Styles and rcParams
Transform the look of your plots instantly. In our final episode, we explore how to use pre-defined style sheets and dynamically customize global settings using rcParams.
4m 09s

Episodes

1

The Core Identity: Figures, Axes, and Interfaces

3m 27s

Welcome to Matplotlib. In this episode, we define the mental model at the heart of Python's most popular visualization library. Learn the difference between a Figure and an Axes, and why the explicit Object-Oriented interface is your best tool.

Download
Hi, this is Alex from DEV STORIES DOT EU. Matplotlib, episode 1 of 5. You copy a plotting solution from Stack Overflow, paste it into your code, and suddenly your new chart is overwriting the old one. The code looks right, but it behaves like a Frankenstein monster. This happens because most online examples mix two completely different ways of using the library without explaining why. To fix this, you need to understand The Core Identity: Figures, Axes, and Interfaces. Matplotlib is the bedrock of Python visualization. Pandas, Seaborn, and many other libraries run on top of it. But developers often stumble on its architecture. To write clean visualization code, you must separate the container from the content. In Matplotlib, this means understanding the difference between a Figure and an Axes. The Figure is your canvas. It is the top-level container that holds the entire window, the background, and all the elements inside it. But a Figure does not draw data. For that, you need an Axes. The Axes is the actual plot. It is the region where your lines, bars, and scatter points live. A Figure can hold multiple Axes, like a grid of four subplots. Keep in mind, Axes is not the plural of the word axis. An Axes object contains two or three individual Axis objects, which handle the specific number lines and ticks. You attach data to the Axes, and the Axes is attached to the Figure. Once you know what these objects are, you have to decide how to interact with them. This is where the confusion starts. Matplotlib gives you two distinct ways to build a chart: the implicit interface and the explicit interface. The implicit interface relies on a module called pyplot. It tracks the state of your program behind the scenes. When you call a plotting function directly, Matplotlib assumes you want to draw on the currently active Figure and Axes. If none exist, it creates them for you. This is highly convenient for a quick, throwaway script where you just need to inspect some data fast. But because it relies on hidden global state, it becomes unpredictable in larger applications. The explicit interface, often called the object-oriented interface, removes the guesswork. You instantiate your objects up front. First you create the Figure and the Axes together, then you call methods directly on those specific objects. You never rely on the library to guess which plot you are targeting. If you are building a reusable dashboard, always use the explicit interface. You can write helper functions that take an Axes object as an argument, plot data onto it, and return it. The function does not care about the global state of the application. It just modifies the object it was handed. This makes your code modular and testable. Here is the key insight. You can use either method, but you should never mix them. Use the implicit pyplot interface for rapid exploration in a notebook, and use the explicit object-oriented interface for production code. If you enjoy the show and want to support us, you can find us by searching for DevStoriesEU on Patreon. That is all for this one. Thanks for listening, and keep building!
2

The Lifecycle of a Plot

3m 25s

Discover how to take a plot from raw data to a labeled, formatted display. We walk through the lifecycle of a simple chart, showing you exactly how to add labels, titles, and custom tick formatters using the explicit interface.

Download
Hi, this is Alex from DEV STORIES DOT EU. Matplotlib, episode 2 of 5. Formatting numbers on an axis can feel like a wrestling match. You want a clean hundred K with a dollar sign, but you get scientific notation or raw integers crowding the screen. The fix is remarkably simple once you learn how to hand control of your axis directly to a standard Python function. Today, we look at the lifecycle of a plot using the explicit axes interface. The explicit interface treats charting as a predictable, step-by-step process. You are always calling methods on a specific object. The lifecycle begins by creating a figure and an axes object. The figure is the blank canvas. The axes object represents the actual area where your data will live. Once you have that axes object, every customization is just another method call applied to it. Consider a scenario where you have a list of company names and a list of their revenue numbers. To get this data onto the screen, you call a plotting method on the axes. For a horizontal bar chart, you call bar h and pass in the names and the revenue. At this point, you have a functional plot, but it lacks context. The next phase of the lifecycle is adding that context. A common approach is to set the title, the x label, and the y label individually. However, the axes object has a unified set method. You can call set and pass keyword arguments for the title, the x label, and the y label all at once. This single line of code handles the structural text of your chart. If you ever need to inspect what is currently applied, you can use the corresponding get methods, like get x tick labels, to retrieve the current state before you change it. This brings us to the most critical part of fine-tuning: formatting the axis numbers. When you plot revenue, large numbers create messy axes. Matplotlib might display one hundred thousand with all its zeros. You want it to say one hundred K with a dollar sign. Here is the key insight. You do not need to dig through obscure Matplotlib settings to fix this. You just write a plain Python function. You define a function that takes two arguments: the tick value and its position. Inside this function, you write standard Python logic. You check if the value is in the thousands, divide it by one thousand, and return a formatted string with a dollar sign and a capital K. To apply this, you tell the axes object to use your function for its tick marks. You access the x-axis property on your axes object, and then you call a method named set major formatter. You pass your custom function directly into this method. Matplotlib takes over from there. As it draws the plot, it passes every single tick value on the x-axis through your Python function and displays the clean string you returned. The explicit interface removes the guesswork from customizing charts by breaking it down into a reliable sequence: you create the axes, map the raw data, apply your labels through a single set method, and intercept the tick formatting entirely with your own logic. That is all for this one. Thanks for listening, and keep building!
3

Mastering Layouts: Subplots and Mosaics

3m 47s

Learn how to manage multiple plots on a single canvas without them overlapping. This episode covers plt.subplots, the power of subplot_mosaic for semantic layouts, and using constrained layout to keep things tidy.

Download
Hi, this is Alex from DEV STORIES DOT EU. Matplotlib, episode 3 of 5. You need to build a dashboard with a wide header chart and two smaller charts below it. In the past, this meant calculating grid fractions and manually placing axes. Now, you can build that exact layout by typing an ASCII art string. This is Mastering Layouts: Subplots and Mosaics. Most data visualizations start with a basic grid. When you need a two-by-two layout, you call the standard subplots function, specify the number of rows and columns, and Matplotlib hands you back a figure object and a multi-dimensional array containing your individual axes. You use standard array indexing to select a specific axis and draw your data. That works perfectly until you add text. By default, Matplotlib positions axes based on fixed proportions of the figure size. It does not account for the physical space taken up by your titles, axis labels, or tick marks. As a result, the X axis labels of your top row will often overlap the titles of your bottom row. Instead of writing custom spacing adjustments, you should handle this at the figure creation stage. Pass the layout argument set to the word constrained. Constrained layout is an optimization engine. Right before the figure is drawn, it measures the bounding boxes of all your text elements and pushes the axes apart just enough to prevent collisions. Standard subplots and constrained layouts cover symmetrical grids. But dashboards are rarely symmetrical. You often need charts that span multiple rows or columns. This brings us back to the wide header chart spanning the top row, with two smaller charts side-by-side underneath. Instead of dealing with low-level grid specification objects, you can use a semantic method called subplot mosaic. You call subplot mosaic directly on your figure object. It accepts a visual representation of your layout, written entirely in strings. Each unique character you type represents a discrete chart. If a character is repeated across rows or columns, that chart stretches to fill those spaces. To build our dashboard layout, you can pass a single string where rows are separated by semicolons. For the top row, you type the capital letter A twice. Then a semicolon. For the bottom row, you type the capital letter B, then the capital letter C. The entire string is simply A A semicolon B C. Matplotlib parses this string and sees that A occupies two columns in the first row, so it creates one wide axis spanning the top. It sees B and C occupy one column each in the second row, so it creates two smaller axes below. Here is the key insight. Because standard arrays lose meaning in complex layouts, subplot mosaic does not return an array. It returns a standard Python dictionary. The keys of this dictionary are the exact string characters you mapped out in your design. If you want to draw a line chart on your wide header, you simply access the dictionary using the key A. If you want to put a scatter plot in the bottom right, you access the dictionary using the key C. Your plotting code becomes completely decoupled from grid coordinates. You can also use this system to create intentional white space. If you want an empty gap in your grid, you put a period character in your layout string. Matplotlib reads the period and leaves that specific grid cell completely blank. Complex grid math is a thing of the past. Modern layout design is just typing the visual shape you want and letting the dictionary map your data to the exact right space on the screen. That is all for this one. Thanks for listening, and keep building!
4

Beyond the Line: Exploring Core Plot Types

3m 43s

Move beyond basic lines and scatter plots. We map out Matplotlib's plot categories, contrasting statistical distribution plots with gridded data functions like imshow and pcolormesh.

Download
Hi, this is Alex from DEV STORIES DOT EU. Matplotlib, episode 4 of 5. You have ten thousand data points, you throw them onto a scatter plot, and you end up with a giant, unreadable ink blob where the overlapping points hide the actual pattern. You chose a pairwise tool for a density problem. Getting past the default line chart requires knowing how to match your data's shape to the right visual tool, which is exactly what we cover in Beyond the Line: Exploring Core Plot Types. Matplotlib organizes its core plots into broad categories based on the structure of your data. The three foundational categories are pairwise data, statistical distributions, and gridded data. The most basic shape is pairwise. You have an array of X values and a matching array of Y values. You use the plot function when these points have a logical sequence, like a time series, where drawing a continuous line between them shows a trend. If the points are independent observations, you use the scatter function to place individual markers. But scatter plots break down when you have high density. That brings us to the second category, which handles statistical distributions. Here is the key insight. When you have ten thousand overlapping points, you do not actually care about the exact coordinate of point number four thousand. You care about where the points cluster. This is where a function like hexbin steps in. It takes the same X and Y arrays as a scatter plot but groups the geometric area into hexagonal bins, coloring them based on point density to reveal the hidden pattern. Now consider a single array containing the raw ages of all your customers. Plotting them one by one as dots gives you useless noise. Instead, you feed that single flat list into the hist function. A histogram automatically groups the individual ages into ranges and shows you the volume of customers in their twenties compared to their fifties. If you need to compare those age distributions across five different store locations side by side, you switch to a boxplot. The boxplot summarizes the ranges, medians, and outliers cleanly. If you need more detail than a boxplot provides, a violinplot draws the full curved shape of the density profile for each store. The third major category is gridded data. This applies when your data is a two-dimensional matrix and you need to visualize a continuous value across an area. Think of a two-dimensional temperature map across a geographical grid. Every position has an X coordinate, a Y coordinate, and a temperature value. You do not want lines or scattered points to represent this. You want a solid, colored surface. Matplotlib provides imshow and pcolormesh for this purpose. You use imshow when your data sits on a perfectly regular grid, like the pixels of a digital photograph. It assumes equal spacing between every data point and renders very quickly. If your grid coordinates are irregular, perhaps your measurement boundaries warp or compress near certain geographical features, you use pcolormesh. It calculates and draws individual quadrilaterals for every single cell, conforming exactly to the distorted shape of your coordinate arrays. When deciding which Matplotlib function to call, ignore what you want the final picture to look like and look strictly at the mathematical shape of your input arrays: are they sequential pairs, flat lists, or two-dimensional matrices. That is all for this one. Thanks for listening, and keep building!
5

Power-User Workflows: Styles and rcParams

4m 09s

Transform the look of your plots instantly. In our final episode, we explore how to use pre-defined style sheets and dynamically customize global settings using rcParams.

Download
Hi, this is Alex from DEV STORIES DOT EU. Matplotlib, episode 5 of 5. You often see people write twenty lines of repetitive code tweaking tick labels, grid lines, and fonts for every single plot they make. A single command can apply all those changes instantly across an entire project. This episode covers Power-User Workflows: Styles and rcParams. The standard Matplotlib look is highly recognizable, but manually updating individual elements per plot to match a specific aesthetic is inefficient. Instead, you use style sheets. Matplotlib ships with several built-in styles. You call a function named style dot use from the pyplot module and pass a string, like ggplot or classic. If you are preparing a visualization for a dark-themed presentation slide, you do not need to manually change the background to black, the axes to white, and the text to light gray. You run style dot use with dark underscore background at the top of your script. Every figure generated after that line instantly inherits that specific look. You can even combine style sheets. If you pass a list of style names, Matplotlib applies them in order from left to right. The styles listed on the right will overwrite overlapping settings from the styles on the left. Here is the key insight. Calling style dot use changes the global state for the rest of your Python session. If you only want a specific style for one particular chart, you use a context manager called style dot context. You open the context, specify the style name, and write your plotting code inside that block. Once the block ends, your plots revert to whatever global style was active before. Underneath these style sheets is a massive configuration dictionary called rcParams. The r and c stand for runtime configuration. Every default property Matplotlib uses to render a figure lives in this dictionary. Font sizes, line widths, default figure dimensions, and marker styles are all mapped to specific string keys. When you apply a style sheet, you are essentially bulk-updating the rcParams dictionary in the background. But you can also interact with it directly to make granular, dynamic adjustments. Say you applied a style you like, but the default line width is too thin for your needs. You access the rcParams dictionary, specify the key for lines dot linewidth, and assign it a new numerical value. From that point on, every line drawn in your session defaults to that thicker width. Matplotlib also provides a convenience function called rc to handle this. Instead of modifying the dictionary key by key, you call rc, pass a top-level group name like font, and then provide keyword arguments for the specific properties like weight or size. It is a much cleaner way to update several related settings at once. You can also define your own custom styles. A style sheet is simply a text file with a dot mplstyle extension. Inside, it contains a simple list of rcParams key-value pairs. You save this file, pass its path to style dot use, and your custom corporate branding is instantly applied to any plot without polluting your actual data code. The real power of Matplotlib customization is decoupling your data logic from your aesthetic choices. Setting rules globally keeps your plotting functions lean and ensures visual consistency across your entire codebase. I encourage you to explore the official documentation to see the full list of available runtime configurations and try building a custom style sheet yourself, or visit devstories dot eu to suggest topics for future series. Thanks for spending a few minutes with me. Until next time, take it easy.