Sitemap
Marzieh Vahdat

Marzieh Vahdat

MatPlotlib Training

17 min readJan 3, 2026

--

Matplotlib is the foundational plotting library in Python — the tool that almost every other visualization library builds on. Here’s why it’s worth using:

1. It’s the Standard for Python Plotting

Matplotlib is the core of Python’s visualization ecosystem. Libraries like Pandas, Seaborn, SciPy, and even machine‑learning tools rely on it under the hood.

2. Extremely Flexible

You can create:

  • simple line plots
  • histograms
  • bar charts
  • scatter plots
  • heatmaps
  • complex multi‑panel scientific figures

Matplotlib gives you full control over every element of a figure — fonts, colors, axes, ticks, annotations, and more.

3. MATLAB‑like Interface (Easy for Beginners)

Matplotlib was originally designed to emulate MATLAB’s plotting commands so scientists and engineers could switch to Python easily.

4. Works Everywhere

It integrates with:

  • Jupyter notebooks
  • Python scripts
  • GUI apps (Tkinter, Qt, GTK)

This makes it ideal for research, teaching, dashboards, and production systems.

5. Huge Community & Longevity

Because it’s been around since 2003, Matplotlib has:

  • extensive documentation
  • thousands of tutorials
  • a massive user community
  • stable, reliable behavior

History of Matplotlib

Here’s the story behind the library, based on the official documentation and historical sources.

Origins

Matplotlib was created by John D. Hunter, a neurobiologist, in the early 2000s. He wanted a free, open‑source alternative to MATLAB for scientific visualization.

First Release (2003)

The initial public release of Matplotlib happened in 2003. Its goal: make it possible to create high‑quality 2D plots in Python with very few commands.

MATLAB‑Inspired Design

Hunter wrote that Matplotlib was built so users could “create simple plots with just a few commands” and that it was inspired by MATLAB’s ease of use.

Growth and Adoption

Over time, Matplotlib became the default plotting library for the entire scientific Python ecosystem. SciPy, Pandas, and many other libraries adopted it as their visualization backend.

After John Hunter

John D. Hunter passed away in 2012, but the project continued under the Matplotlib development team and the NumFOCUS Foundation, which he helped found.

Modern Matplotlib

Today, Matplotlib is:

  • actively maintained
  • highly optimized
  • still the backbone of Python visualization
  • at version 3.x with continuous improvements

Matplotlib basics

Matplotlib is Python’s core plotting library used to create static, animated, and interactive visualizations. It provides a MATLAB‑like interface (pyplot) and a more powerful object‑oriented API. It’s widely used in data science, engineering, and research.

The Absolute Basics (Pyplot Style)

  1. Import the library
import matplotlib.pyplot as plt
import numpy as np

2. Your first plot

The simplest Matplotlib workflow is:

plt.plot([1, 2, 3, 4], [1, 4, 2, 3])
plt.show()

This creates a figure, draws a line plot, and displays it. This exact example appears in the official quick‑start guide.

The Matplotlib Mental Model

Matplotlib has two main concepts:

✔ Figure

The entire window or page where plots appear.

✔ Axes

The actual plot area (x‑y coordinate system). A figure can contain multiple axes (subplots).

The official docs describe this clearly:

“Matplotlib graphs your data on Figures… each of which can contain one or more Axes.”

Creating a Figure and Axes (Recommended Way)

fig, ax = plt.subplots()   # Create a figure with one axes
ax.plot([1, 2, 3], [1, 4, 2])
plt.show()

This is the object‑oriented API, which is cleaner and more powerful.

Common Plot Types

  1. Line Plot
ax.plot(x, y)

2. Scatter Plot

ax.scatter(x, y)

3. Bar Chart

ax.bar(categories, values)

4. Histogram

ax.hist(data, bins=20)

5. Multiple Plots (Subplots)

fig, axs = plt.subplots(2, 2)
axs[0,0].plot(x, y)
axs[1,1].hist(data)

Customizing Your Plot

Titles and labels

ax.set_title("My Plot")
ax.set_xlabel("X Axis")
ax.set_ylabel("Y Axis")

Grid

ax.grid(True)

Colors and styles

ax.plot(x, y, color='red', linestyle='--', marker='o')

A Complete Minimal Example

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)
y = np.sin(x)

fig, ax = plt.subplots()
ax.plot(x, y, label="Sine wave")
ax.set_title("Basic Matplotlib Plot")
ax.set_xlabel("x")
ax.set_ylabel("sin(x)")
ax.legend()
plt.show()

%matplotlib

%matplotlib tells Jupyter how to display Matplotlib plots.

Different backends change:

  • whether plots are static or interactive
  • whether they appear inside the notebook or in a separate window
  • whether you can zoom, pan, resize, etc.

%matplotlib inline

What it does

  • Renders static images (PNG) of your plots inside the notebook.
  • This is the default in Jupyter Notebook and JupyterLab.
  • Fast, simple, reliable.

When to use it

  • When you want quick, clean plots.
  • When you don’t need interactivity (zooming, panning, toolbars).
%matplotlib inline
import matplotlib.pyplot as plt

plt.plot([1,2,3])
plt.show()

Behavior

  • Every plot is saved as a static image in the output cell.
  • Good for reports, tutorials, and simple visualizations.

%matplotlib notebook

What it does

  • Enables interactive Matplotlib plots inside the notebook.
  • Adds a toolbar: zoom, pan, save, resize.
  • Plots update dynamically without re‑rendering the whole cell.

When to use it

When you want:

  • zooming
  • panning
  • rotating 3D plots
  • interactive exploration
%matplotlib notebook
import matplotlib.pyplot as plt

plt.plot([1,2,3])
plt.show()

Behavior

  • Plots are rendered using an interactive JavaScript backend.
  • You can interact with the figure like a GUI window.

%matplotlib widget

If %matplotlib notebookdoesn’t work in VSCode, then use %matplotlib widget, but you need to have ipympl.

!pip install ipympl
%matplotlib widget

import matplotlib.pyplot as plt
plt.plot([1, 2, 3])
plt.show()

plt.figure()

In Matplotlib, plt.figure() creates a new, empty figure — basically a blank canvas on which you can draw plots.

Think of it like opening a new page in a sketchbook. Without it, Matplotlib will draw everything on the current figure.

You use plt.figure() when you want to:

  1. Create multiple separate plots

If you don’t call plt.figure(), Matplotlib keeps drawing on the same figure.

import matplotlib.pyplot as plt

plt.plot([1,2,3])
plt.figure() # new canvas
plt.plot([4,5,6])
plt.show()

This produces two separate windows/figures.

2. Control the size or resolution of a figure

You can set width, height, and DPI:

plt.figure(figsize=(8, 4), dpi=120)
plt.plot([1, 2, 3])

What is dpi in plt.figure(figsize=(8, 4), dpi=120)?

DPI stands for Dots Per Inch.

It controls how many pixels Matplotlib uses to render your figure.

  • Higher DPI → sharper, more detailed image
  • Lower DPI → more pixelated, less detailed image

Matplotlib uses:

  • figsize → physical size of the figure in inches
  • dpi → pixels per inch

So the total pixel resolution is:

width in pixels=figsizex⋅dpi

height in pixels=figsizey⋅dpi

For your example:

plt.figure(figsize=(8, 4), dpi=120)
  • Width: 8×120=960 pixels
  • Height: 4×120=480 pixels

So the figure is 960 × 480 pixels.

Why does DPI matter?

When saving images

Higher DPI gives crisp images for:

  • papers
  • reports
  • posters
  • presentations

Example:

plt.savefig("plot.png", dpi=300)

When displaying on high‑resolution screens

High DPI prevents blurry plots.

3. Prepare multiple figures in the same script

Useful in dashboards, reports, or experiments.

plt.figure(1)
plt.plot([1,2,3])

plt.figure(2)
plt.plot([10,20,30])

4. Avoid plots overlapping

If you forget to call plt.figure(), your plots may stack on top of each other unintentionally.

When you don’t need plt.figure()

If you’re making just one simple plot, you can skip it:

plt.plot([1,2,3])
plt.show()

Matplotlib will automatically create a default figure for you.

FIGURE vs SUBPLOTS — The Core Difference

1. Figure = the entire canvas

A figure is the whole window or page where your plots live.

  • It’s the outer container.
  • You can have one figure or many figures.
  • A figure can contain one or multiple subplots.

2. Subplots = individual plots inside the figure

A subplot is an axes object — the actual area where a graph is drawn.

  • A figure can have 1 subplot or many subplots arranged in a grid.
  • Each subplot has its own x/y axes, title, labels, etc.

Think of subplots as the small boxes drawn on your sheet of paper.

Example: One Figure, Multiple Subplots

import matplotlib.pyplot as plt

fig = plt.figure(figsize=(8, 6)) # the canvas

# 2 rows, 2 columns → 4 subplots
ax1 = fig.add_subplot(2, 2, 1)
ax2 = fig.add_subplot(2, 2, 2)
ax3 = fig.add_subplot(2, 2, 3)
ax4 = fig.add_subplot(2, 2, 4)

ax1.plot([1,2,3])
ax2.plot([3,2,1])
ax3.plot([1,3,2])
ax4.plot([2,1,3])

plt.show()

or:

fig, axs = plt.subplots(2, 2)

axs[0, 0].plot([1, 2, 3])
axs[0, 1].plot([3, 2, 1])
axs[1, 0].plot([1, 3, 2])
axs[1, 1].plot([2, 1, 3])

plt.show()

plt.show()

plt.show() displays the figure(s) you have created with Matplotlib.

Think of it as:

“Okay Matplotlib, now actually draw everything on the screen.”

Without plt.show(), your plots may not appear — especially in scripts.

Why do we need plt.show()?

1. To display the plot in a window (in scripts)

If you’re running a Python script (like script.py), nothing will appear until you call :

plt.show()

This opens the plot window.

2. To pause the program until the plot window is closed

In scripts, plt.show() blocks execution until you close the figure window.

3. To finalize and render all pending plots

Matplotlib collects drawing commands internally. plt.show() tells it:

“Render everything now.”

In Jupyter Notebook?

In Jupyter, plots often appear automatically, so plt.show() is optional — but still useful for:

  • controlling when a plot appears
  • avoiding overlapping plots
  • showing multiple figures cleanly

How to Save a Plot in Matplotlib

The main command is:

plt.savefig("filename.png")

This saves the current figure to a file.

You can save in many formats

Just change the extension:

plt.savefig("plot.jpg")
plt.savefig("plot.pdf")
plt.savefig("plot.svg")
plt.savefig("plot.png")

Matplotlib automatically detects the format from the extension.

Control resolution with dpi

plt.savefig("plot.png", dpi=300)

Higher DPI = sharper image (useful for reports or printing).

Save a specific figure (object‑oriented style)

If you created a figure using fig, ax = plt.subplots():

fig, ax = plt.subplots()
ax.plot([1, 2, 3])

fig.savefig("figure1.png")

This is cleaner when working with multiple figures.

Matplotlib advance

fig.add_axes()

fig.add_axes() is one of Matplotlib’s lower‑level, object‑oriented ways to manually place an Axes (a plotting area) anywhere you want inside a Figure.

It gives you full control over the exact position and size of a subplot.

It adds a new Axes (subplot) to a figure at a specific position, defined in figure coordinates.

The syntax:

ax = fig.add_axes([left, bottom, width, height])

Each value is between 0 and 1, representing a fraction of the figure size.

  • left → distance from left edge
  • bottom → distance from bottom
  • width → width of the axes
  • height → height of the axes
import matplotlib.pyplot as plt

fig = plt.figure()

# Add an axes at a custom position
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])
ax.plot([1, 2, 3])
ax.set_title("Custom Axes")

plt.show()

This places the plot exactly where you specify.

Why use fig.add_axes()?

1. When you want precise control

Unlike plt.subplots(), which arranges plots in a grid, add_axes() lets you place plots anywhere.

2. To create inset plots

Small plots inside a bigger plot.

inset = fig.add_axes([0.6, 0.6, 0.25, 0.25])
inset.plot([1, 2, 3])

3. For custom layouts

Dashboards, unusual arrangements, or artistic layouts.

legends

A legend is the box that explains what each line, marker, or color in your plot represents. It maps labels to the visual elements.

How to create a legend

1. Automatic legend with plt.legend()

If you give your plot elements a label, calling plt.legend() will display them.

import matplotlib.pyplot as plt

plt.plot([1,2,3], label="Line A")
plt.plot([3,2,1], label="Line B")

plt.legend() # shows the legend
plt.show()

2. Object-oriented style with ax.legend()

When using subplots:

fig, ax = plt.subplots()
ax.plot([1,2,3], label="Line A")
ax.plot([3,2,1], label="Line B")

ax.legend()

Legend customization

You can control placement, size, and style:

plt.legend(loc="upper left")        # position
plt.legend(fontsize=12) # font size
plt.legend(title="My Legend") # add a title
plt.legend(frameon=False) # remove box frame

Common loc options:

  • "upper left", "upper right", "lower left", "lower right"
  • "center", "best" (Matplotlib chooses automatically)

bbox_to_anchor in legend()

  • Purpose: Controls the exact position of the legend box relative to the axes or figure.
  • It takes a tuple (x, y) or (x, y, width, height) in axes coordinates (0–1 range).
  • Works together with loc (like "upper left", "center", etc.) to fine‑tune placement.

Example:

import matplotlib.pyplot as plt

plt.plot([1,2,3], label="Line A")
plt.plot([3,2,1], label="Line B")

# Place legend outside the plot, to the right
plt.legend(loc="upper left", bbox_to_anchor=(1, 1))
plt.show()

Here:

  • loc="upper left" anchors the legend’s corner.
  • bbox_to_anchor=(1, 1) moves that corner to position (1,1) — the top‑right outside the axes.

borderaxespad in legend()

  • Purpose: Controls the padding (space) between the legend box and the axes border.
  • It’s a float value (in font‑size units).
  • Larger values push the legend farther away from the axes.

Example:

plt.plot([1,2,3], label="Line A")
plt.plot([3,2,1], label="Line B")

plt.legend(loc="upper right", borderaxespad=2)
plt.show()

control how the axes are scaled

xscale and yscale in Matplotlib control how the axes are scaled. They let you switch between linear, logarithmic, symlog, or logit scales, which is super useful when your data spans wide ranges or has special distributions.

  • plt.xscale() → sets the scaling of the x‑axis
  • plt.yscale() → sets the scaling of the y‑axis

By default, both axes are linear (values increase evenly). You can change them to other scales for better visualization.

  1. Linear (default)
plt.xscale("linear")
plt.yscale("linear")

Values increase evenly.

Get Marzieh Vahdat’s stories in your inbox

Join Medium for free to get updates from this writer.

2. Logarithmic

plt.xscale("log")
plt.yscale("log")
  • Useful when data spans several orders of magnitude.
  • Each tick represents a power of 10 (or another base).
  • Example: scientific data, exponential growth.

3. Symlog (symmetric log)

plt.yscale("symlog", linthresh=0.1)
  • Like log scale, but handles negative values too.
  • linthresh defines the range around zero that stays linear.

4. Logit

plt.yscale("logit")
  • Useful for probabilities (0–1 range).
  • Expands values near 0 and 1.

Example

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0.1, 100, 100)
y = x**2

plt.plot(x, y, label="y = x^2")

plt.xscale("log") # log scale on x-axis
plt.yscale("linear") # keep y-axis linear

plt.legend()
plt.show()

This shows how a quadratic function looks when the x‑axis is logarithmic.

Understanding matplotlib.ticker.MultipleLocator and AutoMinorLocator

Both are tick locator classes in matplotlib.ticker that control where ticks appear on axes.

1. MultipleLocator

  • Purpose: Places ticks at multiples of a given base.
  • Syntax:
from matplotlib.ticker import MultipleLocator
ax.xaxis.set_major_locator(MultipleLocator(5))
  • Effect: Major ticks every 5 units (0, 5, 10, 15, …).
  • Works for major or minor ticks depending on where you set it.

Use when you want fixed, predictable tick spacing.

2. AutoMinorLocator

  • Purpose: Automatically generates minor ticks between major ticks.
  • Syntax:
from matplotlib.ticker import AutoMinorLocator
ax.xaxis.set_minor_locator(AutoMinorLocator(2))
  • Effect: Subdivides each major tick interval into n parts.
  • AutoMinorLocator(2) → 1 minor tick halfway between major ticks.
  • AutoMinorLocator(5) → 4 minor ticks evenly spaced.
  • Default: 4 or 5 subdivisions depending on major tick spacing.

Use when you want automatic minor ticks that adapt to scaling.

Example Comparison

import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator, AutoMinorLocator

fig, ax = plt.subplots()

ax.plot(range(50))

# Major ticks every 10 units
ax.xaxis.set_major_locator(MultipleLocator(10))

# Minor ticks: 4 subdivisions between majors
ax.xaxis.set_minor_locator(AutoMinorLocator(5))

plt.grid(which='major', color='red')
plt.grid(which='minor', color='blue', linestyle='--')
plt.show()
  • Red grid lines = major ticks (every 10).
  • Blue dashed lines = minor ticks (every 2 units, since 10 ÷ 5 = 2).

set_xlim and set_ylim

  • ax.set_xlim() → sets the x‑axis limits of a plot.
  • ax.set_ylim() → sets the y‑axis limits of a plot.

They belong to the Axes object (ax), so you use them when working in the object‑oriented style.

ax.set_xlim([xmin, xmax])
ax.set_ylim([ymin, ymax])
  • xmin, xmax → minimum and maximum values for the x‑axis
  • ymin, ymax → minimum and maximum values for the y‑axis
import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)
y = np.sin(x)

fig, ax = plt.subplots()
ax.plot(x, y)

# Set axis limits
ax.set_xlim(2, 8) # show only x from 2 to 8
ax.set_ylim(-0.5, 1) # restrict y between -0.5 and 1

plt.show()

Here:

  • The x‑axis will only display values between 2 and 8.
  • The y‑axis will only display values between -0.5 and 1.

Why use them?

  • Zoom in on a specific region of your data.
  • Standardize plots so multiple figures have the same axis ranges.
  • Improve readability by cutting off irrelevant ranges.

set_xticks and set_yticks

ax.set_xticks()

Sets the positions of ticks on the x‑axis.

ax.set_yticks()

Sets the positions of ticks on the y‑axis.

They do not set labels by themselves — they only set where ticks appear.

fig, ax = plt.subplots()

ax.plot([1, 2, 3, 4])

ax.set_xticks([0, 1, 2, 3, 4])
ax.set_yticks([0, 5, 10, 15])

This forces ticks to appear exactly at those values.

Adding custom labels

If you want custom text for each tick, use set_xticklabels or set_yticklabels:

ax.set_xticks([0, 1, 2, 3])
ax.set_xticklabels(['zero', 'one', 'two', 'three'])

Why use them?

  • To control spacing of ticks
  • To show only important values
  • To clean up cluttered axes
  • To match ticks across multiple subplots

How they differ from locators

  • set_xticks() → manual, you specify exact tick positions
  • MultipleLocator, AutoMinorLocator → automatic, Matplotlib calculates positions for you

Use set_xticks() when you want full control.

Annotation

Annotations are one of the most powerful features in Matplotlib because they let you point to something on your plot and explain it directly. They’re perfect for highlighting peaks, labeling important points, or adding explanatory text.

An annotation is text + an optional arrow pointing to a specific location on your plot.

You create one using:

ax.annotate(text, xy, xytext, arrowprops)

Key Parameters

1. text

The text you want to display.

2. xy=(x, y)

The point you want to annotate (where the arrow points).

3. xytext=(x_text, y_text)

The location of the text.

4. arrowprops={...}

A dictionary that defines the arrow style.

Basic Example

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)
y = np.sin(x)

fig, ax = plt.subplots()
ax.plot(x, y)

ax.annotate(
"Peak here",
xy=(np.pi/2, 1), # point to annotate
xytext=(2, 1.5), # text position
arrowprops=dict(arrowstyle="->", color="red")
)

plt.show()

This draws an arrow pointing to the peak of the sine wave.

Common Customizations

Arrow styles

arrowprops=dict(arrowstyle="->")
arrowprops=dict(arrowstyle="fancy")
arrowprops=dict(arrowstyle="wedge")

Text styling

fontsize=12
color="blue"
bbox=dict(boxstyle="round", fc="yellow", alpha=0.3)

Coordinate systems

You can annotate using:

  • data coordinates (xycoords='data')
  • axes fraction (xycoords='axes fraction')
  • figure fraction (xycoords='figure fraction')

Example:

ax.annotate("Top left", xy=(0.05, 0.95), xycoords='axes fraction')

Why annotations are useful

  • Highlight important points
  • Add explanations directly on the plot
  • Label peaks, intersections, or anomalies
  • Create professional, publication‑quality figures

Using text() instead of annotate()

Basic syntax

ax.text(x, y, "your text")
  • (x, y) → the location of the text (in data coordinates by default)
  • "your text" → the string you want to display

Example

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)
y = np.sin(x)

fig, ax = plt.subplots()
ax.plot(x, y)

# Add text at a specific point
ax.text(3, 0.5, "Important point", fontsize=12, color="red")

plt.show()

This places the text directly at (3, 0.5) on the plot.

Useful customizations

Font size, color, rotation

ax.text(5, 0.8, "Peak", fontsize=14, color="blue", rotation=30)

Background box

ax.text(2, -0.5, "Note", bbox=dict(boxstyle="round", fc="yellow", alpha=0.3))

Different coordinate systems

You can place text relative to the axes instead of data:

ax.text(0.05, 0.95, "Top-left", transform=ax.transAxes)
  • (0,0) = bottom-left of axes
  • (1,1) = top-right of axes

This is great for titles, labels, or notes that shouldn’t move with the data.

Matplotlib’s patches

Matplotlib’s patches are powerful building blocks for drawing shapes — circles, polygons, rectangles, arrows, and more. When you want to draw many shapes efficiently, you combine them into a PatchCollection.

Let me give you a clean, practical guide to using:

  • matplotlib.patches.Circle
  • matplotlib.patches.Polygon
  • matplotlib.collections.PatchCollection

1. Using Circle

A Circle is a patch that draws a filled or outlined circle.

from matplotlib.patches import Circle

circle = Circle((x_center, y_center), radius, facecolor='blue', edgecolor='black')
ax.add_patch(circle)

Example:

import matplotlib.pyplot as plt
from matplotlib.patches import Circle

fig, ax = plt.subplots()

c = Circle((0.5, 0.5), 0.3, facecolor='skyblue', edgecolor='black')
ax.add_patch(c)

ax.set_aspect('equal')
plt.show()

2. Using Polygon

A Polygon draws any shape defined by a list of vertices.

from matplotlib.patches import Polygon

points = [(0,0), (1,0), (0.5,1)]
poly = Polygon(points, closed=True, facecolor='orange', edgecolor='black')
ax.add_patch(poly)

Example:

fig, ax = plt.subplots()

triangle = Polygon([(0,0), (1,0), (0.5,1)], closed=True,
facecolor='yellow', edgecolor='black')
ax.add_patch(triangle)

ax.set_aspect('equal')
plt.show()

3. Using PatchCollection

When you have many shapes, adding them one by one is slow. PatchCollection lets you group them and apply colors, transparency, and colormaps efficiently.

from matplotlib.collections import PatchCollection

Example: Circles + Polygons in a collection

import matplotlib.pyplot as plt
from matplotlib.patches import Circle, Polygon
from matplotlib.collections import PatchCollection

fig, ax = plt.subplots()

patches = []

# Add circles
for i in range(5):
patches.append(Circle((i, i), 0.3))

# Add polygons
patches.append(Polygon([(2,4), (3,5), (1,5)], closed=True))

# Create collection
collection = PatchCollection(patches, facecolor='lightgreen', edgecolor='black', alpha=0.7)
ax.add_collection(collection)

ax.set_xlim(-1, 6)
ax.set_ylim(-1, 6)
ax.set_aspect('equal')

plt.show()

Why use PatchCollection?

  • Faster rendering for many shapes
  • Apply one color, one alpha, or one colormap to all patches
  • Cleaner code when drawing dozens or hundreds of objects

ax.set_aspect('equal')

This forces the plot to use equal scaling on both axes.

Useful when you want shapes to look correct:

  • Circles look like circles
  • Squares look like squares
  • Geometry plots
  • Maps

ax.set_aspect('auto')

This is the default. Matplotlib stretches the plot to fill the available space, even if it distorts shapes.

Numeric aspect ratio

You can specify a ratio:

ax.set_aspect(2)   # y-units are twice as tall as x-units

Meaning:

  • 1 unit in x
  • 2 units in y (visually)

Pie chart

A pie chart in Matplotlib is one of the simplest ways to show parts of a whole. It displays data as slices of a circle, where each slice’s size corresponds to its value.

A pie chart shows percentages or proportions. Each slice represents a category, and the whole circle represents 100%.

Use it when:

  • You want to compare parts of a whole
  • You have a small number of categories
  • Exact values are less important than relative proportions

Basic pie chart in Matplotlib

import matplotlib.pyplot as plt

sizes = [40, 25, 20, 15]
labels = ['A', 'B', 'C', 'D']

plt.pie(sizes, labels=labels)
plt.show()

This creates a simple pie chart with four slices.

Useful options

  1. Add percentages
plt.pie(sizes, labels=labels, autopct='%1.1f%%')

2. Explode (pull out) a slice

explode = [0.1, 0, 0, 0]  # explode first slice
plt.pie(sizes, labels=labels, explode=explode)

3. Add colors

colors = ['gold', 'skyblue', 'lightgreen', 'salmon']
plt.pie(sizes, labels=labels, colors=colors)

4. Make it a perfect circle

Matplotlib sometimes stretches the pie; fix it with:

plt.axis('equal')

Full example with everything

import matplotlib.pyplot as plt

sizes = [40, 25, 20, 15]
labels = ['A', 'B', 'C', 'D']
explode = [0.1, 0, 0, 0]

plt.pie(
sizes,
labels=labels,
explode=explode,
autopct='%1.1f%%',
shadow=True,
startangle=90
)

plt.axis('equal')
plt.show()

A pie chart normally starts at 0°, which is the positive x‑axis (pointing to the right). startangle rotates the starting point. The rotation is counter‑clockwise. This rotates the pie so the first slice starts at the top (90°).

bar chart

A bar chart is one of the most common and useful plot types in Matplotlib. It displays categorical data using rectangular bars whose heights (or lengths) represent values.

A bar chart shows comparisons between categories. Each bar corresponds to a category, and its height represents the value.

Use it when:

  • You have discrete categories (e.g., months, products, groups)
  • You want to compare values side‑by‑side
  • Exact numerical differences matter

Basic bar chart in Matplotlib

import matplotlib.pyplot as plt

categories = ['A', 'B', 'C', 'D']
values = [10, 24, 36, 18]

plt.bar(categories, values)
plt.show()

This creates a simple vertical bar chart.

Horizontal bar chart

plt.barh(categories, values)

Useful when category names are long.

Common customizations

  1. Colors
plt.bar(categories, values, color='skyblue')

2. Add labels

plt.xlabel("Category")
plt.ylabel("Value")
plt.title("Simple Bar Chart")

3. Add value labels on top of bars

for i, v in enumerate(values):
plt.text(i, v + 0.5, str(v), ha='center')

4. Change bar width

plt.bar(categories, values, width=0.6)

Grouped (side‑by‑side) bar chart

import numpy as np

x = np.arange(len(categories))
values1 = [10, 20, 30, 40]
values2 = [15, 18, 22, 35]

plt.bar(x - 0.2, values1, width=0.4, label='Group 1')
plt.bar(x + 0.2, values2, width=0.4, label='Group 2')

plt.xticks(x, categories)
plt.legend()
plt.show()

plt.xticks(x, categories) is a convenient Matplotlib command that lets you set the positions and labels of the x‑axis ticks in one line.

It’s essentially a shortcut for:

  • set_xticks(x) → where the ticks go
  • set_xticklabels(categories) → what text appears at those ticks

Optional formatting

You can rotate labels:

plt.xticks(x, categories, rotation=45)

Or change font size:

plt.xticks(x, categories, fontsize=12)

Stacked bar chart

plt.bar(categories, values1, label='Group 1')
plt.bar(categories, values2, bottom=values1, label='Group 2')
plt.legend()

Histogram

A histogram in Matplotlib is a plot that shows the distribution of numerical data by grouping values into bins and displaying how many data points fall into each bin. It’s one of the most useful tools for understanding the shape of your data.

A histogram divides data into bins (intervals) and counts how many values fall into each one. Matplotlib uses the function:

plt.hist(data)

This creates bars where each bar’s height represents the frequency of values in that bin.

This matches the definition from multiple sources:

  • A histogram is a “graph showing frequency distributions”.
  • It “divides the data into bins and counts the frequency of values in each bin”.
  • It is a “graphical representation of data distribution”

Basic Example

import matplotlib.pyplot as plt
import numpy as np

data = np.random.normal(100, 15, 1000) # random data

plt.hist(data, bins=30)
plt.title("Simple Histogram")
plt.xlabel("Values")
plt.ylabel("Frequency")
plt.show()

np.random.normal(100, 15, 1000) generates 1,000 random numbers drawn from a normal (Gaussian) distribution with:

  • Mean (loc) = 100
  • Standard deviation (scale) = 15
  • Size = 1000 samples

This matches the definition of numpy.random.normal, which draws samples from a normal distribution with parameters loc, scale, and size.

np.random.normal(loc=100, scale=15, size=1000)
  • loc = 100 → center of the distribution (mean)
  • scale = 15 → spread of the distribution (standard deviation)
  • size = 1000 → number of random values to generate

This example follows the same pattern shown in the search results, where random data is used to demonstrate histograms.

Useful Parameters

Matplotlib’s hist() supports many options:

Press enter or click to view image in full size

Example:

plt.hist(data, bins=20, color='skyblue', edgecolor='black')

2D Histogram (optional)

Matplotlib also supports 2D histograms when you have two variables:

plt.hist2d(x, y, bins=30)

This is shown in the official documentation example where both 1D and 2D histograms are demonstrated.

3D plotting

from mpl.toolkits.mplot3d import Axes3D is the classic import used to enable 3D plotting in Matplotlib. It loads the Axes3D class, which creates a 3D axes object inside a Matplotlib figure.

Axes3D is the 3D Axes object used by Matplotlib to draw 3D plots such as:

  • 3D scatter plots
  • 3D line plots
  • 3D surface plots
  • 3D bar charts

The Matplotlib documentation describes it as the class that provides 3D axes inside a figure.

Basic usage

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt

fig = plt.figure()
ax = Axes3D(fig) # create a 3D axes

Modern (recommended) way

You no longer need to import Axes3D directly. Matplotlib automatically registers 3D projection support.

Use this instead:

import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

This is the preferred method according to the Matplotlib documentation.

Example: 3D scatter plot

import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

x = np.random.rand(50)
y = np.random.rand(50)
z = np.random.rand(50)

ax.scatter(x, y, z)
plt.show()

The 111 in fig.add_subplot(111, projection='3d') is a compact code that tells Matplotlib how to arrange subplots. The meaning is confirmed in the search results: it is a three‑digit integer representing (nrows, ncols, index).

adds a 3D subplot that occupies the entire figure.

Break the digits apart:

  • 1 → number of rows
  • 1 → number of columns
  • 1 → index (position of the subplot)

This means:

Create a single subplot that fills the entire figure.

The StackOverflow explanation shows that codes like 221, 222, etc., map to positions in a grid of subplots.

For example:

  • 221 → 2 rows, 2 columns, position 1 (top‑left)
  • 222 → 2 rows, 2 columns, position 2 (top‑right)
  • 223 → bottom‑left
  • 224 → bottom‑right

--

--