PLOTTING AND CHARTS
Matplotlib Tutorials
Matplotlib draws the charts almost every other Python plotting tool is built on. These 200 tutorials cover it one task at a time — every chart type, every axis and tick setting, and the errors that stop a figure from appearing.
- 200 tutorials
- 22 topics
- Every chart type
What Matplotlib is for
Matplotlib is the plotting library the rest of the Python data stack leans on. Pandas .plot() calls it underneath, Seaborn is a friendlier layer on top of it, and scikit-learn’s example gallery draws with it. Learning it once means you can read and fix almost any Python chart you meet.
The library has two ways in, which is the single biggest source of confusion. pyplot is the quick, stateful interface — plt.plot(), plt.title(), done. The object-oriented interface gives you a figure and its axes as real objects (fig, ax = plt.subplots()) and you call methods on those. Quick look at some data: use pyplot. Anything you will reuse, put on a dashboard, or arrange as several panels: use the object-oriented one.
Most day-to-day Matplotlib work is not choosing a chart type. It is the finishing: rotating tick labels so dates stop overlapping, moving a legend out of the data, fixing a y-axis that starts at an unhelpful number, and saving at a resolution that does not look soft. That is why the tutorials below are grouped by those jobs rather than by module.
Install it and draw something
Matplotlib installs with pip and needs nothing else. If you are on a fresh machine, install NumPy alongside it — almost every example expects arrays, and Pandas brings its own copy anyway.
The one thing worth knowing on day one is where your figure goes. In a script, nothing appears until you call plt.show() or plt.savefig(). In a Jupyter notebook, charts appear under the cell by themselves.
Seeing UserWarning: Matplotlib is currently using agg, which is a non-GUI backend? That means no window can open — usually a server, container or WSL. Save the figure to a file with plt.savefig() instead of calling plt.show().
If you are starting today
A sensible order to learn Matplotlib in
Six steps. Each one is a tutorial you can finish in a sitting, and together they cover what you need for most real charts.
- 1
Draw one line chart
Get a figure on screen and understand the plot, then show, then save sequence before anything else.
- 2
Label the axes and title it
An unlabelled chart is not finished. Axis labels, a title, and control over their font sizes.
- 3
Learn the other chart types
Bar, scatter, pie and histogram cover the overwhelming majority of what people actually need to draw.
- 4
Take control of the axes
Set the range yourself, fix tick labels that overlap, and use a log scale when the data spans orders of magnitude.
- 5
Put several plots together
Subplots, shared axes and
tight_layout()— where the object-oriented interface starts paying off. - 6
Save it properly
PNG for the web, PDF for print, the right dpi, and no white border around the edge.
The thing that confuses everyone
pyplot or fig, ax? Both are Matplotlib
Search for any Matplotlib problem and you get answers written in two different styles. They are two interfaces to the same library, and knowing which one you are looking at makes every other tutorial easier to follow.
The pyplot interface
Quick and statefulYou call functions on plt and it draws on whatever figure is “current”. Short, and fine until you have more than one plot, at which point tracking which figure is current gets confusing.
# plt keeps track of the figure for you plt.plot(months, signups) plt.title("Signups") plt.ylabel("People") plt.show()
Use it when: you want a quick look at some data in a notebook, or the chart is a throwaway.
The object-oriented interface
Explicit and reusableplt.subplots() hands you the figure and its axes as objects, and you call methods on them. Slightly longer, but nothing is implicit — and it is the only sane way to handle several panels.
# you hold the figure and axes yourself fig, ax = plt.subplots(figsize=(10, 6)) ax.plot(months, signups) ax.set_title("Signups") ax.set_ylabel("People") fig.savefig("signups.png")
Use it when: the chart gets reused, saved, or drawn as a grid of subplots. Most of the tutorials below use this style.
Quick reference
The Matplotlib calls you will use most
Fourteen lines that cover the majority of everyday plotting. Each one has a full tutorial in the sections below.
| Task | Code | Worth knowing |
|---|---|---|
| Line chart | plt.plot(x, y) | Add marker="o" to show the data points. |
| Bar chart | plt.bar(labels, values) | Use barh() for horizontal bars. |
| Scatter plot | plt.scatter(x, y) | s= sets size, c= sets colour. |
| Histogram | plt.hist(data, bins=20) | Bin count changes the story — try a few. |
| Pie chart | plt.pie(values, labels=labels) | Add autopct="%1.1f%%" for percentages. |
| Axis labels | plt.xlabel("Month") | And plt.ylabel(). Never skip these. |
| Chart title | plt.title("New signups") | fontsize= controls the size. |
| Legend | plt.legend() | Needs label= on each plotted series. |
| Axis range | plt.ylim(0, 100) | Stops a misleading auto-scaled y-axis. |
| Rotate tick labels | plt.xticks(rotation=45) | The fix for overlapping dates. |
| Grid lines | plt.grid(True, alpha=0.3) | Keep them faint so they stay in the background. |
| Figure size | plt.figure(figsize=(10, 6)) | In inches, before you plot anything. |
| Grid of plots | fig, ax = plt.subplots(2, 2) | Then call methods on ax[0][1]. |
| Save to a file | plt.savefig("chart.png", dpi=150) | Add bbox_inches="tight" to trim the border. |
Every tutorial, by topic
Every Matplotlib tutorial, grouped by what you are trying to do
The old version of this page listed all 200 of these in one long column. They are the same tutorials, sorted into the 22 jobs people actually come here for.
Errors and fixes
10Start here when something is wrong rather than missing: a blank saved image, a plot that never appears, or an AttributeError on a name you are sure exists. Error bars live here too, since that is what most people are searching for when they type “matplotlib error”.
Install and setup
5Installing, upgrading and removing Matplotlib, plus the two setup questions that come up constantly — what %matplotlib inline does, and why a non-GUI backend stops your window opening.
3D plots
18Three-dimensional scatter plots and surfaces: colour, marker size, the view angle, depth shading, and the axis limits that behave differently once you add a third dimension.
Bar charts
18Vertical, horizontal, stacked, grouped and multi-series bars, built from lists, dictionaries and DataFrames — with value labels on top, which is the part people always come back for.
Scatter plots
9Marker shape, size and transparency, colour maps and outlines, legends that make sense, and scatter plots drawn over a date axis.
Pie and donut charts
10Percentage formatting with autopct, exploding a slice, shadows and hatching, donut variants, and several pies in one figure.
Histograms and distributions
4Histograms, box plots and violin plots — for when you want the shape of the data rather than individual points.
Dates and time axes
8Time on the x-axis is its own skill: date formatting, sensible tick spacing, a vertical marker at a particular date, and limits set with datetimes.
Horizontal and vertical lines
14Reference lines drawn across a plot — targets, thresholds, averages and cut-off dates — with labels, text and shaded bands between them.
Grid lines
4Turning the grid on, restricting it to one axis, styling and colouring it, and controlling grid spacing across a set of subplots.
Line styles and dashes
4Dashed and dotted lines, the exact dash spacing, and combining a dashed line with visible markers.
Multiple plots on one figure
10Several lines on one set of axes — different colours, the same colour, different lengths, drawn in a loop, or read from a CSV.
Line plots
6The plain line chart, plus best-fit lines and curves and log-log plots for data that spans several orders of magnitude.
Shapes, surfaces and other plots
6Surfaces, heatmaps, polar plots and plotting straight from a NumPy array — the chart types that do not fit the usual four.
Tick marks and tick labels
13Rotating labels so dates stop overlapping, setting tick positions yourself, removing ticks or labels entirely, and controlling their font size, colour and alignment.
Axis limits and scales
7Setting the x and y range with xlim and ylim, switching to a log scale, and applying one range across every subplot at once.
Two and secondary y-axes
5Plotting two series with different units on one chart: a secondary y-axis, shared axes, and matched or independent scales.
Axis labels and titles
15Axis labels, titles, subplot titles and an overall figure title, plus free text placed anywhere on the plot — and the font sizes for all of it.
Legends
3Moving the legend outside the plot area so it stops covering your data, legends inside subplots, and transparent legend styling.
Colors and styling
5Figure and axes background colours, transparent backgrounds for saved images, and colour bars attached to individual subplots.
Subplots and figure layout
11Building a grid of plots, setting the figure size, spacing and margins between panels, and what to do when subplots_adjust() appears to do nothing.
Saving and exporting
10Saving to PNG and PDF at the dpi you want, without a border, including a single axis, an array as an image, or many pages in one PDF.
More Matplotlib tutorials
5Everything that does not sit neatly under one heading, including interview questions and updating a plot inside a loop.
Keep going
What to learn next to it
Matplotlib is rarely used on its own. These are the libraries you will reach for in the same script.
Questions people ask
Frequently asked questions
Is Matplotlib still worth learning in 2026?
Yes, and it is still the sensible first choice for static charts. Pandas, Seaborn and scikit-learn all draw with Matplotlib underneath, so understanding it means you can customise and fix their output instead of being stuck with the defaults. Plotly and Altair are better for interactive web charts, but they do not replace it.
Should I use plt.plot() or fig, ax = plt.subplots()?
Use plt.plot() for a quick look at some data in a notebook. Use fig, ax = plt.subplots() for anything you will reuse, save, or arrange as multiple panels, because you then have the figure and axes as objects and can set each one explicitly. Mixing the two in one script is what causes most confusing behaviour.
Why does my Matplotlib plot not show up?
In a plain Python script nothing is drawn until you call plt.show(). If you have called it and still see no window, you are probably on a server, container or WSL with no display, so Matplotlib falls back to the non-GUI Agg backend. Save the figure with plt.savefig("chart.png") instead.
How do I stop my x-axis labels overlapping?
Rotate them. plt.xticks(rotation=45, ha="right") fixes most cases, and adding plt.tight_layout() stops the rotated labels being cut off when you save. For dates, Matplotlib’s date locators will also thin the ticks out for you.
What is the difference between Matplotlib and Seaborn?
Seaborn is built on top of Matplotlib. It gives you good-looking statistical charts in one line and understands DataFrames directly, but every Seaborn plot is a Matplotlib figure underneath. In practice people draw with Seaborn and then adjust it with Matplotlib calls.
How do I save a chart without the white border around it?
Pass bbox_inches="tight" and pad_inches=0 to savefig(). Add transparent=True if you want the background to disappear as well, which is useful when the image goes on a coloured page.
Pick a chart and draw it
You will learn more from finishing one labelled, saved chart than from reading three more tutorials about it.