cat 0020-introduction-to-matplotlib.md
Introduction to Matplotlib
This tutorial covers the essential Matplotlib concepts for data visualization, using a step‑by‑step approach with mental models and practical examples.
1. Introduction
What is Matplotlib?
Matplotlib is a Python library used to create visualizations.
For example, instead of looking at this:
Age: 51, 52, 53, 54, 55
Chol: 210, 230, 190, 250, 220we can turn the data into a graph:
Cholesterol
|
250| ●
230| ●
210| ● ●
190| ●
+-------------------------
51 52 53 54 55
AgeThe graph makes patterns much easier to see.
Matplotlib is one of the most widely used Python libraries for creating static, interactive, and publication-quality visualizations.
It also works very well with libraries such as NumPy and Pandas.
Why learn Matplotlib?
- Visualization is essential for understanding data before applying Machine Learning.
- Flexibility – you can customize almost every element of a plot.
- Integration – it’s the backbone of plotting in Pandas and many other libraries.
Importing Matplotlib
Let’s start by importing the necessary libraries:
import matplotlib.pyplot as plt
import numpy as np
import pandas as pdIf you're using Jupyter Notebook or Colab, add this magic command to display plots inline:
%matplotlib inline2. Two Ways to Plot: Pyplot vs Object-Oriented
Matplotlib offers two main approaches:
- Pyplot (functional) – Quick and simple, but less flexible for complex plots.
- Object‑Oriented (OO) – More explicit and powerful; recommended for advanced work.
Both approaches can produce the same types of charts. The main difference is how we control the chart.
Pyplot Method
The Pyplot approach is the simpler approach.
plt.plot([1, 2, 3, 4])
plt.show()This uses the global plt interface. It's useful when you want to create a quick visualization without needing much customization.
Object‑Oriented Method
The Object-Oriented approach is a little more explicit.
# Create a figure and an axes object
fig, ax = plt.subplots()
# Plot data on the axes
ax.plot([1, 2, 3, 4])
# Display the plot
plt.show()The OO method gives you explicit control over the Figure (the whole canvas) and Axes (the actual plot area). It’s the recommended approach for anything beyond simple plots.
Mental model:
Figure= the entire sheet of paper.Axes= the plot(s) drawn on that paper.plt.subplots()creates both and returns them.
┌─────────────────────────────┐
│ Figure │
│ │
│ ┌─────────────────┐ │
│ │ Axes │ │
│ │ │ │
│ │ Graph │ │
│ │ │ │
│ └─────────────────┘ │
│ │
└─────────────────────────────┘You can also create a figure and add axes manually:
fig = plt.figure() # create an empty figure
ax = fig.add_subplot() # add a single subplot
ax.plot(x, y) # Plot data on the axesBut plt.subplots() is more convenient and is the standard.
3. Plotting Basics
Let's explore the most common plot types:
- Line plot → shows trends or changes
- Scatter plot → shows relationships between variables
- Bar plot → compares categories
- Histogram → shows the distribution of numerical data
Line Plot
A line plot connects data points with a line. It's commonly used when we want to see how something changes.
x = np.linspace(0, 10, 100) # 100 points from 0 to 10
y = x ** 2
fig, ax = plt.subplots()
ax.plot(x, y)
plt.show()Scatter Plot
A scatter plot displays individual points instead of connecting them with lines. Scatter plots are useful for showing relationships between two variables.
fig, ax = plt.subplots()
ax.scatter(x, np.exp(x)) # scatter plot of exponential
plt.show()A simple mental model:
Scatter plot = put a dot wherever an
(x, y)value exists.
It's often useful when asking questions like:
"Does one variable have a relationship with another variable?"
Bar Plot
Bar charts compare categories. We can plot from a dictionary:
nut_butter_prices = {
"Almond butter": 10,
"Peanut butter": 8,
"Cashew butter": 12
}
fig, ax = plt.subplots()
ax.bar(nut_butter_prices.keys(), nut_butter_prices.values())
ax.set(title="Nut Butter Prices", xlabel="Nut Butter", ylabel="Price ($)")
plt.show()For horizontal bars, use barh:
ax.barh(list(nut_butter_prices.keys()), list(nut_butter_prices.values()))Histogram
Histograms show the distribution of a dataset.
data = np.random.randn(1000) # 1000 random numbers from normal distribution
fig, ax = plt.subplots()
ax.hist(data)
plt.show()A histogram groups values into ranges called bins and shows how many values fall into each range. Think of it as:
"Where are most of my values concentrated?"
This makes histograms particularly useful when exploring a dataset before Machine Learning.
4. Subplots
You can create multiple plots in the same figure using plt.subplots().
For example:
┌───────────┬───────────┐
│ Plot 1 │ Plot 2 │
├───────────┼───────────┤
│ Plot 3 │ Plot 4 │
└───────────┴───────────┘
This is useful when you want to compare multiple visualizations together.
Option 1: Using Tuple Unpacking
fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(
nrows=2,
ncols=2,
figsize=(10, 10)
)
ax1.plot(x, x/2)
ax2.scatter(np.random.random(10), np.random.random(10))
ax3.bar(nut_butter_prices.keys(), nut_butter_prices.values())
ax4.hist(np.random.randn(1000))Here nrows=2 and ncols=2 means:
Create 2 rows × 2 columns = 4 Axes.
Each Axes can contain its own plot.
Option 2: Using Indexed Axes
fig, ax = plt.subplots(nrows=2, ncols=2, figsize=(10, 10))
ax[0, 0].plot(x, x/2)
ax[0, 1].scatter(np.random.random(10), np.random.random(10))
ax[1, 0].bar(nut_butter_prices.keys(), nut_butter_prices.values())
ax[1, 1].hist(np.random.randn(1000))Here ax is an array containing all four Axes.
You can access them using their row and column:
ax[0, 0] ax[0, 1]
ax[1, 0] ax[1, 1]Tip: figsize=(width, height) controls the size of the whole figure in inches.
5. Plotting from Pandas DataFrames
Pandas DataFrames have built-in plotting methods that use Matplotlib under the hood.
This means you can often create a visualization directly from a DataFrame without manually calling ax.plot(), ax.scatter(), etc.
Prepare the Data
data = {
"Make": ["Toyota", "Honda", "toyota", "Ford", "BMW", "Honda", "TOYOTA", "Ford", "BMW", "Nissan"],
"Model": ["Corolla", "Civic", "Camry", "Focus", "3 Series", "Accord", "RAV4", "Fiesta", "5 Series", "Altima"],
"Year": [2015, 2018, 2017, 2016, 2019, 2020, 2014, 2018, 2017, 2016],
"Price": ["$15,000", "$18,500", "$16,200", "$10,000", "$35,000", "$22,000", "$14,500", "$12,000", "$32,500", "$17,000"],
"Odometer (KM)": [120000, 60000, 85000, 130000, 45000, 20000, 150000, 90000, 55000, 100000],
"Doors": [4, 4, 4, 5, 4, 4, 4, 3, 4, 4],
"Color": ["White", "Black", "Red", "Blue", "Silver", "White", "Red", "Green", "Black", "Blue"]
}
car_sales = pd.DataFrame(data)The Price column is currently a string. We need to convert it to a numeric type:
car_sales["Price"] = (
car_sales["Price"]
.astype(str)
.str.replace("$", "", regex=False)
.str.replace(",", "", regex=False)
.astype(float)
.astype(int)
)Add a Sale Date column and compute cumulative sales:
car_sales['Sale Date'] = pd.date_range(start='1/1/2020', periods=len(car_sales))
car_sales['Total Sales'] = car_sales['Price'].cumsum()cumsum() means cumulative sum. For example:
Price: 100 200 300
Total Sales: 100 300 600
It keeps adding each new value to the previous total.
Line Plot from DataFrame
car_sales.plot(x='Sale Date', y='Total Sales', kind='line')Here:
x→ column used for the x-axisy→ column used for the y-axiskind→ type of plot
Scatter Plot
car_sales.plot(x='Odometer (KM)', y='Price', kind='scatter')This helps us visually investigate the relationship between:
Odometer → PriceFor example:
Do cars with more kilometers generally have lower prices?
Bar Plot
# For a DataFrame, you can plot all numeric columns
df = pd.DataFrame(np.random.rand(10, 4), columns=['a', 'b', 'c', 'd'])
df.plot(kind='bar')Or specify x and y:
car_sales.plot(x='Make', y='Odometer (KM)', kind='bar')Histogram
car_sales['Odometer (KM)'].plot(kind='hist', bins=15)This lets us see the distribution of the cars' odometer values.
6. Customizing Your Plots
Creating a chart is only the first step. We often need to customize it so that the information is easier to understand.
Common customizations include:
- Styles
- Colors
- Axis limits
- Legends
- Titles
- Labels
- Reference lines
Styles
Matplotlib comes with many built-in styles.
View them with:
plt.style.availableApply a style:
plt.style.use('seaborn-v0_8-whitegrid')
car_sales['Price'].plot()Experiment with different styles like 'ggplot', 'seaborn-v0_8', etc.
The style mainly changes the overall appearance of your charts.
Colors and Colormaps
In scatter plots, you can color points by a third variable using c and choose a colormap with cmap:
fig, ax = plt.subplots(figsize=(10, 6))
scatter = ax.scatter(
x=over_50['age'],
y=over_50['chol'],
c=over_50['target'],
cmap='winter'
)Here:
c=over_50['target']means:
Use the
targetvalue to determine the color of each point.
And:
cmap='winter'specifies which color mapping to use.
So a scatter plot can show three pieces of information:
X position → age
Y position → cholesterol
Color → targetAxis Limits
Use set_xlim() and set_ylim() to zoom in or control the visible range:
ax.set_xlim([50, 80])
ax.set_ylim([60, 200])set_xlim()→ controls the x-axis rangeset_ylim()→ controls the y-axis range
Legends
When using scatter with c, add a legend:
ax.legend(*scatter.legend_elements(), title='Target')The legend helps the viewer understand what the different colors represent.
Mean Lines
Add a horizontal line at the mean:
ax.axhline(over_50['chol'].mean(), linestyle='--')Here:
over_50['chol'].mean()calculates the average cholesterol level.
Then axhline() draws a horizontal line at that value.
This gives us a useful reference point when looking at the data.
Adding Titles and Labels
Use ax.set() to set multiple properties at once:
ax.set(
title="Heart Disease and Cholesterol Levels",
xlabel="Age",
ylabel="Cholesterol"
)This gives the chart context:
Title → What is this chart about?
X-axis → What does the horizontal axis represent?
Y-axis → What does the vertical axis represent?For a figure-level title:
fig.suptitle("Heart Disease Analysis", fontsize=16, fontweight='bold')The difference is:
ax.set(title=...)
↓
Title for one Axes
fig.suptitle(...)
↓
Title for the entire Figure7. Saving Figures
Save your figure using fig.savefig():
fig.savefig("heart-disease-analysis-plot.png")This saves the entire figure, including all subplots, to the current directory.
This is useful when you want to use your visualization later in:
- Reports
- Presentations
- Documentation
- Projects
8. Real-World Example: Heart Disease Analysis
Let's load a dataset and apply everything we've learned.
The goal here isn't just to make a chart. It's to use visualization to ask questions about the data.
Load Data
First, download the dataset from the link below and place it in your current working directory:
Download matplotlib-heart-disease.csv
Then read it with Pandas:
heart_disease = pd.read_csv("path/to/matplotlib-heart-disease.csv")
heart_disease.head()head() lets us quickly inspect the first few rows of the dataset.
Filter Patients Over 50
over_50 = heart_disease[heart_disease['age'] > 50]This keeps only rows where:
age > 50Scatter Plot with Pyplot Method
over_50.plot(
kind='scatter',
x='age',
y='chol',
c='target',
figsize=(10, 6)
)We're visualizing:
Age → X-axis
Cholesterol → Y-axis
Target → ColorScatter Plot with OO Method (from DataFrame)
fig, ax = plt.subplots(figsize=(10, 6))
over_50.plot(
kind='scatter',
x='age',
y='chol',
c='target',
ax=ax
)The important part here is:
ax=axThis tells Pandas to use the Axes we already created. This is useful because we can then customize that Axes using Matplotlib.
Fully Customized OO Scatter Plot
fig, ax = plt.subplots(figsize=(10, 6))
scatter = ax.scatter(
x=over_50['age'],
y=over_50['chol'],
c=over_50['target'],
cmap='winter'
)
ax.set(
title="Heart Disease and Cholesterol Levels",
xlabel="Age",
ylabel="Cholesterol"
)
ax.legend(*scatter.legend_elements(), title='Target')
ax.axhline(over_50['chol'].mean(), linestyle='--')
plt.show()Here we're combining several concepts:
Create Figure + Axes
↓
Add data
↓
Set colors
↓
Add title and labels
↓
Add legend
↓
Add mean reference line
↓
DisplaySubplot with Two Scatter Plots
Now let's compare two different relationships in one figure:
- Cholesterol vs age
- Maximum heart rate vs age
fig, (ax0, ax1) = plt.subplots(
nrows=2,
ncols=1,
figsize=(10, 10),
sharex=True
)
# First subplot: cholesterol vs age
scatter = ax0.scatter(over_50['age'], over_50['chol'], c=over_50['target'], cmap='winter')
ax0.set(title="Heart Disease and Cholesterol Levels", ylabel="Cholesterol")
ax0.legend(*scatter.legend_elements(), title="Target")
ax0.axhline(over_50['chol'].mean(), linestyle='--')
# Second subplot: max heart rate vs age
scatter = ax1.scatter(over_50['age'], over_50['thalach'], c=over_50['target'], cmap='winter')
ax1.set(title="Heart Disease and Max Heart Rate", xlabel="Age", ylabel="Max Heart Rate")
ax1.legend(*scatter.legend_elements(), title="Target")
ax1.axhline(over_50['thalach'].mean(), linestyle='--')
fig.suptitle("Heart Disease Analysis", fontsize=16, fontweight='bold')
plt.show()Notice:
sharex=TrueBoth plots use age on the x-axis, so sharing the x-axis makes comparison easier.
The final result is one Figure containing two related visualizations.
9. Key Takeaways
- Two main approaches: pyplot (quick) and object‑oriented (explicit, recommended).
- Common plots: line, scatter, bar, histogram.
- Subplots let you arrange multiple plots in one figure.
- Pandas integration makes it easy to plot directly from DataFrames.
- Customization includes styles, colors, colormaps, axis limits, legends, and mean lines.
- Always save your figures with
fig.savefig()when you want to keep them.
Mental model:
Think of a figure as a canvas, and axes as the individual plots you draw on it. For most visualizations, think:
Create Figure + Axes
↓
Add Data
↓
Customize
↓
Show / SaveThe most important distinction to remember is:
Figure = the whole canvas
Axes = the actual plotting areaOnce this mental model is clear, the different Matplotlib functions become much easier to understand.
With these skills, you can create informative and visually appealing charts for data analysis and Machine Learning projects.