6. Matplotlib Overview#
6.1. Introduction#
Matplotlib is the foundational plotting library in the Python ecosystem, originally developed by John D. Hunter to provide MATLAB-like plotting capabilities in Python. It offers a rich, programmatic interface for producing publication-quality 2D graphics. For a history and introduction of Matplotlib, see matplotlib.org’s History section.
For data scientists, Matplotlib is valuable both as a plotting tool and as the underlying engine for fine-grained customization when presentation quality and plot element control matter.
Matplotlib sits at a low level in the Python visualization stack:
Many higher-level libraries, such as Pandas plotting methods and Seaborn, build on top of it.
It interoperates smoothly with NumPy arrays and the broader scientific Python toolchain.
It can be used through two main interfaces:
The stateful pyplot API is convenient for quick, one-off plots.
The object-oriented (OO) API is the recommended default for most work because it makes figure and axes management explicit.
A useful rule of thumb is:
Use
plt.plot()for quick interactive work.Use
plt.subplots()for most real plotting tasks.Use
fig.add_axes()when you need manual placement or inset axes.
Matplotlib has excellent official documentation and examples at https://matplotlib.org/ (see the Tutorials and Examples).
6.1.1. Installation#
You’ll need to install matplotlib first with either using pip in the terminal:
pip install matplotlib ### in terminal with .venv enabled
or using %pip in the notebook:
%pip install matplotlib ### in Jupyter Notebook
Import the matplotlib.pyplot module with alias plt:
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
6.1.2. Two Styles of Matplotlib Syntax#
There are two common styles of Matplotlib plotting:
Stateful pyplot style: concise and convenient for quick plots.
Object-oriented (OO) style: more explicit and easier to scale to multi-axes figures.
Note on rendering visualizations:
In Jupyter notebooks, plots usually display automatically.
Outside notebooks, you will often need
plt.show()to display the figure window.In older Jupyter/IPython setups,
%matplotlib inlinemay still be needed.
6.2. Stateful Matplotlib#
The MATLAB-style pyplot API uses stateful functions such as plt.plot(), plt.xlabel(), and plt.title() to build a figure. It is useful for quick exploration, but it becomes harder to manage as figures grow more complex.
6.2.1. Basic Matplotlib Commands#
The table below compares common plt.plot() tasks with the corresponding Pandas df.plot() usage.
Task |
Matplotlib plt.plot() |
Pandas df.plot() |
Notes |
|---|---|---|---|
figsize |
|
|
Use |
To plot |
|
|
Uses DataFrame/Series directly; x defaults to index if omitted. |
X label |
|
|
|
Y label |
|
|
Same pattern as label. |
Title |
|
|
Pandas supports |
Pandas .plot() is a convenience wrapper around Matplotlib for quick DataFrame visualization. Compared with plt.plot(), the main differences are:
Feature |
|
Pandas |
|---|---|---|
Typical use |
Fine-grained, figure-level control |
Fast EDA from DataFrame/Series |
Built on |
Core matplotlib |
Wrapper around matplotlib |
Customization |
Full control |
Limited, but can access underlying axes |
Data Input |
Expects x/y arrays |
Pandas columns/index |
6.2.2. First Plots#
Let’s walk through a simple example with two NumPy arrays. Lists work too, but you’ll usually pass NumPy arrays or Pandas columns, which behave like arrays. The data we want to plot:
import numpy as np
x = np.linspace(0, 5, 11) ### 11 numbers from 0 to 5, inclusive
y = x ** 2
print(f"x {type(x)}: {x}")
print(f"y {type(y)}: {y}")
x <class 'numpy.ndarray'>: [0. 0.5 1. 1.5 2. 2.5 3. 3.5 4. 4.5 5. ]
y <class 'numpy.ndarray'>: [ 0. 0.25 1. 2.25 4. 6.25 9. 12.25 16. 20.25 25. ]
The following code creates a basic line plot:
plt.figure()plt.plot()
plt.figure(figsize=(4,3))
plt.plot(x, y)
[<matplotlib.lines.Line2D at 0x7f8ac07c9ba0>]
You can also create a scatter plot with plt.scatter().
plt.figure(figsize=(4,3))
plt.scatter(x, y)
<matplotlib.collections.PathCollection at 0x7f8abe6cc760>
6.2.3. Labels/Title/Legend#
Common plot customizations include:
color
label (legend information)
x-axis and y-axis labels
title
legend (built from labels)
# plt.plot(x, y, 'r') ### 'r' means color red
# plt.plot(x, y, c='r') ### same as above, we saw this in Pandas plot
plt.figure(figsize=(4,3))
plt.plot(x, y, c='red', label='Red Line') ### same as above, we saw this in Pandas plot
plt.xlabel('X-Axis Title') ### in Pandas plot, this is automatic from column names
plt.ylabel('Y-Axis Title') ### in Pandas plot, this is automatic from column names
plt.title('String Title') ### in Pandas plot, this is "title="
plt.legend() ### to show the label we set above
<matplotlib.legend.Legend at 0x7f8abe523940>
The same plot can be created with Pandas plotting:
df = pd.DataFrame({'x': x, 'y': y}) ### DataFrame with two columns
# df.plot(x='x', y='y', kind="line") ### line plot is default in Pandas; axes is automatically created
# df.plot.line(x='x', y='y') ### same as above
# df.plot(x='x', y='y') ### same as above
df.plot(x = 'x', y = 'y', xlabel='X-Axis Title', ylabel='Y-Axis Title', title='String Title', figsize=(4,3))
### all labels and title can be set in df.plot() directly or from dataframe column names
<Axes: title={'center': 'String Title'}, xlabel='X-Axis Title', ylabel='Y-Axis Title'>
### Exercise: Basic plt.plot() with Customization
# 1. Create x_vals = np.linspace(0, 10, 50) and y_vals = np.sin(x_vals).
# 2. Use plt.figure(figsize=(4, 3)) to set the figure size.
# 3. Plot sin vs x_vals in red with the label "sin(x)".
# 4. Add an x-label "x", y-label "Amplitude", and title "Sine Wave".
# 5. Call plt.legend() to show the label.
### Your code starts here.
### Your code ends here.
<matplotlib.legend.Legend at 0x7f8abe4bb460>
6.2.4. Multiple Plots with plt.subplot()#
plt.subplot() is the older pyplot-style way to place multiple axes in one figure. It is still useful to recognize, but for new code you will usually prefer plt.subplots(), which is clearer and fits the OO workflow better.
Syntax:
plt.subplot(nrows, ncols, plot_number)
### plt.subplot(nrows, ncols, plot_number) ### when you want multiple plots in one figure
### order is important, plot after subplot
plt.figure(figsize=(8,3)) ### create a figure first with specified size
plt.subplot(1, 2, 1) ### subplot (axes, x-by-y) 1 of 1 row, 2 columns
plt.plot(x, y, 'r--') ### 'r--' means red dashed line
plt.subplot(1, 2, 2) ### subplot (axes) 2 of 1 row, 2 columns
plt.plot(y, x, 'g*-'); ### 'g*-' means green line with star markers
### Exercise: Multiple Subplots with plt.subplot()
# 1. Create x = np.linspace(0, 2*np.pi, 100).
# 2. Use plt.figure(figsize=(8, 3)) to set the figure size.
# 3. In subplot position (1, 2, 1), plot np.sin(x) with 'b-' and title "Sine".
# 4. In subplot position (1, 2, 2), plot np.cos(x) with 'g--' and title "Cosine".
### Your code starts here.
### Your code ends here.
6.3. OO API with plt.subplots()#
Although plt.plot() and plt.subplot() are useful for quick work, Matplotlib’s object-oriented (OO) API is the recommended default for creating plots. In the OO approach, you create Figure and Axes objects and then call methods on those objects.
This becomes especially helpful when you have multiple subplots, shared axes, or figure-level layout decisions to manage. For example, ax.set_title() always targets a specific axes, which is safer than relying on the current pyplot state.
Note
But what’s the difference between a figure and an axes?
Figure |
Axes |
|
|---|---|---|
Analogy |
The full canvas/window |
One plot region on that canvas |
What it is |
The top-level container |
The area where data is drawn |
Contains |
One or more Axes |
X/Y axis, ticks, lines, labels, title, legend |
Commonly created by |
|
returned by |
A good mental model is:
Figure
└── Axes (a.k.a. one plot)
├── XAxis
├── YAxis
├── Title
├── Lines / Bars / etc.
└── Legend
Here we will learn two OO workflows:
plt.subplots()for the standard, everyday workflowplt.figure()+fig.add_axes()for manual placement and inset-style layouts
6.3.1. plt.subplots()#
plt.subplots() creates the figure and axes objects in one step and returns them as a tuple.
If you create a single subplot, you typically get one
Axesobject.If you create multiple subplots, you get a NumPy array of
Axesobjects.
Typical syntax:
fig, ax = plt.subplots()
The example below shows the standard one-axes case.
x = np.linspace(0, 10, 50) ### start, stop, number of points
y = np.sin(x)
# fig, ax = plt.subplots() ### single Axes case
# fig, axes = plt.subplots(1, 2) ### multiple Axes case
fig, ax = plt.subplots(figsize=(5,3)) ### unpacking in one step
ax.plot(x, y, 'g--') ### plot on that axes
### common axes methods
ax.set_xlabel('X-Axis Label')
ax.set_ylabel('Y-Axis Label')
ax.set_title('Title via Object-Oriented API')
Text(0.5, 1.0, 'Title via Object-Oriented API')
With subplots(), you can specify the number of rows and columns using the nrows= and ncols= parameters when creating the subplots() object. The example below creates an empty canvas of 1-col by 2-row subplots.
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(6, 2)) ### similar to plt.subplot(1, 2, ith axes)
# fig, axes = plt.subplots(1, 2) ### same as above
In this example above, axes is an array variable containing two Axes objects. Looping over that array is a common pattern when you want to apply the same formatting to each subplot.
print(axes)
[<Axes: > <Axes: >]
Now we have access over the two Axes individually using indexing ([0] and [1]). We may plot them separately.
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(6, 2))
axes[0].plot(x, y, 'r--') ### plot on the first axes
axes[0].set_title('First Plot') ### set title for the first axes
axes[1].plot(y, x, 'g*-') ### plot on the second axes
axes[1].set_title('Second Plot') ### set title for the second axes
# plt.show()
Text(0.5, 1.0, 'Second Plot')
It’s not uncommon to loop through the Axes object then fine tune the plots.
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(6, 2))
for ax in axes:
ax.plot(x, y, 'b')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_title('title')
axes[0].set_title('First Plot') ### set title for the first axes
axes[1].set_title('Second Plot') ### set title for the second axes
### display the figure object
# fig ### to show the figure in some environments
plt.show()
A common issue in Matplotlib is overlapping subplot labels or titles. plt.tight_layout() can automatically adjust spacing so the figure is easier to read. (compare with the plots above)
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(6, 2)) ### similar to plt.subplot(1, 2, ith axes)
for ax in axes:
ax.plot(x, y, 'g--')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_title('title')
fig
plt.tight_layout()
### Exercise: Side-by-Side Subplots with plt.subplots()
# 1. Use plt.subplots(1, 2, figsize=(8, 3)) to create a figure and two axes.
# 2. On axes[0], plot x vs np.sin(x) with 'b-', title "Sine",
# x-label "x", and y-label "y".
# 3. On axes[1], plot x vs np.cos(x) with 'r--', title "Cosine",
# x-label "x", and y-label "y".
# 4. Call plt.tight_layout() at the end.
# (`x` and `np` are already available above.)
### Your code starts here.
### Your code ends here.
6.3.2. Saving Figures#
Matplotlib can save high-quality output in formats such as PNG, JPG, SVG, and PDF.
Use the figure’s savefig method. In the example below, we create a small figure explicitly before saving it:
x = np.linspace(0, 10, 100)
y = np.sin(x)
fig, ax = plt.subplots(figsize=(4, 3))
ax.plot(x, y)
fig.savefig("../../images/filename.png")
A slightly safer pattern is to build the output path first and save only if needed:
import os
fig, ax = plt.subplots(figsize=(4, 3))
ax.plot(x, y)
output_dir = '../../images'
output_file = os.path.join(output_dir, 'filename.png')
if not os.path.exists(output_dir): # check folder
os.makedirs(output_dir)
if not os.path.isfile(output_file): # check file
fig.savefig(output_file)
print(f"Saved: {output_file}")
else:
print(f"File already exists, skipping: {output_file}")
# fig.savefig(output_file)
File already exists, skipping: ../../images/filename.png
6.4. Plot Controls and Methods#
This section focuses on controlling the visible appearance of a figure and Axes.
6.4.1. subplots() Parameters#
Parameter |
Type |
Default |
What It Controls |
Example |
|---|---|---|---|---|
|
int |
1 |
Number of subplot rows |
|
|
int |
1 |
Number of subplot columns |
|
|
tuple |
None |
Figure size |
|
|
int |
rcParams value |
Resolution in dots per inch |
|
|
bool or str |
False |
Share x-axis between subplots |
|
|
bool or str |
False |
Share y-axis between subplots |
|
|
bool |
True |
Return a scalar vs array of axes when possible |
|
For a longer reference, see matplotlib.pyplot.subplots.
6.4.2. Figure-Level Controls#
In contrast to ax methods, figure-level methods act on the whole figure rather than on a single axes. They are especially useful for overall sizing, layout, titles, and exporting.
Method |
What it sets |
|---|---|
|
Master title over all subplots |
|
Auto-fix subplot spacing |
|
Figure size |
|
Save to file (also |
|
Resolution |
|
Manual spacing ( |
|
Add a colorbar tied to an axes |
6.4.3. Axes Formatting Methods#
After creating a figure and axes, the next step is usually formatting. These methods do not change the underlying data; they control how the plot is labeled, styled, and displayed.
Method |
What it sets |
|---|---|
|
Plot data (format string: color + linestyle + marker) |
|
X-axis label |
|
Y-axis label |
|
Title above the plot |
|
Add a legend to that axes |
|
X-axis range |
|
Y-axis range |
|
Toggle grid |
6.4.4. ax.plot() Parameters#
Parameter |
Type |
Default |
What It Controls |
Example |
|---|---|---|---|---|
|
array-like |
— |
Data to plot |
|
|
str or tuple |
auto |
Line color |
|
|
float |
1.5 |
Thickness of the line |
|
|
str |
|
Line style |
|
|
str |
|
Marker shape at each data point |
|
|
float |
6 |
Marker size |
|
|
str |
auto |
Fill color of markers |
|
|
str |
auto |
Edge color of markers |
|
|
float |
1.0 |
Transparency (0 = invisible, 1 = opaque) |
|
|
str |
|
Legend label for the line |
|
|
float |
auto |
Drawing order (higher = on top) |
|
Common linestyle values: '-' (solid), '--' (dashed), '-.' (dash-dot), ':' (dotted).
Common marker values: 'o' (circle), 's' (square), '^' (triangle), 'x' (cross), '+' (plus), '.' (point).
For a full reference, see matplotlib.axes.Axes.plot.
6.5. Styling in Practice#
6.5.1. figsize= at Figure Level#
Figure size and DPI are two of the most common figure-level controls.
figsize=(width, height)uses inches.
This can be set with plt.figure(...) or plt.subplots(...).
x = np.linspace(0, 10, 50) ### start, stop, number of points
y = np.sin(x)
fig, axes = plt.subplots(figsize=(4,3))
### peripherals for the axes object
axes.plot(x, y, 'r')
axes.set_xlabel('x')
axes.set_ylabel('y')
axes.set_title('title')
Text(0.5, 1.0, 'title')
6.5.2. Legends for Axes#
Legends are attached to an axes in the OO API. You typically supply label=... when plotting, then call ax.legend() to display the legend for that axes.
fig = plt.figure(figsize=(4,3), dpi=100)
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])
ax.plot(x, x**2, label="x**2")
ax.plot(x, x**3, label="x**3") ### cubed
ax.legend()
<matplotlib.legend.Legend at 0x7f8abe3a6980>
If the legend overlaps the plotted data, pass a loc= argument to ax.legend() to move it.
Common values include string labels such as 'best', 'upper right', 'upper left', 'lower left', and 'lower right'.
fig, ax = plt.subplots(1, 2, figsize=(6,3), dpi=100)
ax[0].plot(x, x**2, label="lower right")
ax[1].plot(x, x**3, label="best")
ax[0].legend(loc='lower right')
ax[1].legend(loc='best')
# fig. ### Jupyter-specific, just displays that one figure object
<matplotlib.legend.Legend at 0x7f8abe3620b0>
6.5.3. Plot Range set_xlim(), set_ylim()#
You can set axis ranges directly with ax.set_xlim(...) and ax.set_ylim(...), or use ax.axis('tight') to fit the view closely around the data.
In the example below, `axes[2] is zoomed in, only showing the slice of the data where x is between 2 and 5, and y is between 0 and 60. That’s why it looks different from the first two even though it plots the same data.
fig, axes = plt.subplots(1, 3, figsize=(12, 4))
axes[0].plot(x, x**2, x, x**3)
axes[0].set_title("default axes ranges")
axes[1].plot(x, x**2, x, x**3)
axes[1].axis('tight')
axes[1].set_title("tight axes")
axes[2].plot(x, x**2, x, x**3)
axes[2].set_ylim([0, 60]) # y-axis runs from 0 to 60
axes[2].set_xlim([2, 5]) # x-axis runs from 2 to 5
axes[2].set_title("custom axes range");
### Exercise: Controlling Axis Ranges
# 1. Use fig, axes = plt.subplots(1, 2, figsize=(10, 4)).
# 2. On axes[0], plot x vs x**2 and x vs x**3. Set title "Default Range".
# 3. On axes[1], plot the same data, then set:
# - x-axis limits to [1, 4] using set_xlim
# - y-axis limits to [0, 80] using set_ylim
# Set title "Custom Range".
# 4. Call plt.tight_layout() at the end.
# (x is already defined above.)
### Your code starts here.
### Your code ends here.
6.5.4. Colors, Line Width and Style#
Matplotlib gives you many options for customizing colors, line widths, and line styles.
6.5.4.1. MATLAB-style format strings#
Matplotlib supports short MATLAB-style format strings such as 'b.-', which combine color, line style, and marker style in one compact argument.
### MATLAB style line color and style
fig, ax = plt.subplots(figsize=(4,3))
ax.plot(x, x**2, 'b.-') # blue line with dots
ax.plot(x, x**3, 'g--') # green dashed line
### .plot() parameters can also be specified in a more explicit way
ax.scatter(x+1, x**3 + 2, color='purple', marker='.', linestyle='--') # more explicit
<matplotlib.collections.PathCollection at 0x7f8abdc42020>
### Exercise: MATLAB-Style Color and Line Formatting
# 1. Use fig, ax = plt.subplots(figsize=(4, 3)).
# 2. Plot x vs np.sin(x) using 'b.-' (blue line with dots).
# 3. Plot x vs np.cos(x) using 'r--' (red dashed line).
# 4. Set the title to "MATLAB-Style Colors".
# (x and np are already available above.)
### Your code starts here.
### Your code ends here.
Text(0.5, 1.0, 'MATLAB-Style Colors')
6.5.4.2. The color= Parameter#
You can also define colors by name or by RGB hex code, and control transparency with alpha.
fig, ax = plt.subplots(figsize=(4,3), dpi=100)
ax.plot(x, x+1, color="blue", alpha=0.5) ### half-transparent
ax.plot(x, x+2, color="#8B008B") ### RGB hex code
ax.plot(x, x+3, color="#FF8C00") ### RGB hex code
[<matplotlib.lines.Line2D at 0x7f8abd7edd80>]
### Exercise: Colors with the color= Parameter and Alpha
# 1. Use fig, ax = plt.subplots(figsize=(4, 3)).
# 2. Plot x vs x+1 with color="blue" and alpha=0.3.
# 3. Plot x vs x+2 with color="#228B22" (forest green) and alpha=0.7.
# 4. Plot x vs x+3 with color="tomato" and alpha=1.0.
# 5. Set the title to "Color and Transparency".
# (x is already defined above.)
### Your code starts here.
### Your code ends here.
Text(0.5, 1.0, 'Color and Transparency')
6.5.4.3. Line and marker styles#
To change line width, use linewidth or lw. To change line style, use linestyle or ls. Marker shape, size, and colors can also be customized.
fig, ax = plt.subplots(figsize=(4,3))
ax.plot(x, x+1, color="red", linewidth=0.25)
ax.plot(x, x+2, color="red", linewidth=0.50)
ax.plot(x, x+3, color="red", lw=1.00)
ax.plot(x, x+4, color="red", lw=2.00)
### possible linestype options ‘-‘, ‘–’, ‘-.’, ‘:’, or ‘None’ (the default, which means no line will be drawn).
ax.plot(x, x+5, color="green", lw=3, linestyle='-')
ax.plot(x, x+6, color="green", lw=3, ls='-.')
ax.plot(x, x+7, color="green", lw=3, ls=':')
### custom dash
line, = ax.plot(x, x+8, color="black", lw=1.50)
line.set_dashes([5, 10, 15, 10]) ### format: line length, space length, ...
### possible marker symbols: marker = '+', 'o', '*', 's', ',', '.', '1', '2', '3', '4', ...
ax.plot(x, x+ 9, color="blue", lw=3, ls='-', marker='+')
ax.plot(x, x+10, color="blue", lw=3, ls='--', marker='o')
ax.plot(x, x+11, color="blue", lw=3, ls='-', marker='s')
ax.plot(x, x+12, color="blue", lw=3, ls='--', marker='1')
### marker size and color
ax.plot(x, x+13, color="purple", lw=1, ls='-', marker='o', markersize=2)
ax.plot(x, x+14, color="purple", lw=1, ls='-', marker='o', markersize=4)
ax.plot(x, x+15, color="purple", lw=1, ls='-', marker='o', markersize=8, markerfacecolor="red")
ax.plot(x, x+16, color="purple", lw=1, ls='-', marker='s', markersize=8,
markerfacecolor="yellow", markeredgewidth=3, markeredgecolor="green");
### Exercise: Line Width, Style, and Markers
# 1. Use fig, ax = plt.subplots(figsize=(4, 3)).
# 2. Plot x vs x+1: color='red', lw=2, ls='-', marker='o'.
# 3. Plot x vs x+3: color='green', lw=1, ls='--', marker='s'.
# 4. Plot x vs x+5: color='blue', lw=3, ls=':', marker='^',
# markersize=8, markerfacecolor='yellow'.
# 5. Set the title to "Line and Marker Styles".
# (x is already defined above.)
### Your code starts here.
### Your code ends here.
Text(0.5, 1.0, 'Line and Marker Styles')
6.6. Common Plot Types#
So far we have used line plots to introduce Matplotlib. Below are a few common plot types, shown in the OO style so the examples stay consistent with the rest of the notebook.
6.6.1. Scatter Plot#
A scatter plot displays individual data points as dots on a two-dimensional plane, with one variable on the x-axis and another on the y-axis. Each dot represents a single observation. Scatter plots are useful for visualizing the relationship or correlation between two continuous variables, and for identifying patterns, clusters, or outliers in the data.
x = np.linspace(0, 10, 50)
y = np.sin(x)
fig, ax = plt.subplots(figsize=(4,3))
ax.scatter(x, y)
<matplotlib.collections.PathCollection at 0x7f8abddf27a0>
6.6.2. Bar Plot#
A bar plot displays categorical data as rectangular bars, where the height (or length) of each bar is proportional to the value it represents. The x-axis typically shows the categories and the y-axis shows the corresponding values. Bar plots are useful for comparing quantities across distinct groups or categories.
categories = ['A', 'B', 'C', 'D']
values = [3, 7, 5, 6]
fig, ax = plt.subplots(figsize=(4,3))
ax.bar(categories, values)
ax.set_title('Simple Bar Plot')
Text(0.5, 1.0, 'Simple Bar Plot')
6.6.3. Histogram#
A histogram displays the distribution of a continuous variable by dividing the data into bins (intervals) and counting how many values fall into each bin. The x-axis represents the value ranges, and the y-axis represents the frequency (count) of observations in each bin. Histograms are useful for visualizing the shape of a distribution — whether it is symmetric, skewed, or has multiple peaks.
from random import sample
data = sample(range(1, 1000), 100) ### chooses 100 unique random elements from sequence.
fig, ax = plt.subplots(figsize=(4,3))
ax.hist(data)
(array([ 6., 14., 7., 10., 6., 16., 6., 8., 9., 18.]),
array([ 5. , 103.4, 201.8, 300.2, 398.6, 497. , 595.4, 693.8, 792.2,
890.6, 989. ]),
<BarContainer object of 10 artists>)
6.6.4. Boxplot#
A boxplot (also called a box-and-whisker plot) summarizes the distribution of a dataset using five key statistics:
the minimum,
first quartile (Q1),
median,
third quartile (Q3), and
maximum.
Also:
The box: The box spans from Q1 to Q3 (the interquartile range, IQR)
The line: the line inside the box marks the median.
The whiskers: The whiskers extend to the last data points within 1.5 × IQR from Q1 and Q3.
Points/circles beyond the whiskers are plotted individually as outliers.
Boxplots are useful for comparing distributions across multiple groups.
### list comprehension to create multiple datasets with different standard deviations
data = [np.random.normal(0, std, 100) for std in range(1, 4)]
fig, ax = plt.subplots(figsize=(4,3))
### rectangular box plot
ax.boxplot(data, vert=True, patch_artist=True);
### Exercise: Visualizing Sales Data with Different Plot Types
# The following data represent quarterly sales figures ($K) for four products
# and daily website visits over 100 days.
#
# products = ['Laptop', 'Phone', 'Tablet', 'Watch']
# sales = [320, 580, 140, 210]
# visits = np.random.normal(loc=500, scale=80, size=100)
#
# 1. Create a figure with two side-by-side subplots: fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4))
# 2. On ax1, draw a bar chart of products vs. sales.
# Set the title to "Quarterly Product Sales", x-label "Product", y-label "Sales ($K)".
# 3. On ax2, draw a histogram of visits using ax2.hist(visits, bins=15),
# color='orange', edgecolor='white', and alpha=0.7.
# Set the title to "Daily Website Visits", x-label "Visits", y-label "Frequency".
# 4. Call plt.tight_layout() before displaying.
### Your code starts here.
### Your code ends here.
6.7. OO with add_axes()#
fig.add_axes() is a more manual OO technique than plt.subplots(). It is most useful when you want precise axes placement, such as inset plots or custom layouts.
The process of using add_axes() to create plots is:
Create a Figure object.
Add one or more Axes using normalized figure coordinates
[left, bottom, width, height].Plot and format each axes separately.
add_axes() uses normalized figure coordinates. For example, [0.1, 0.1, 0.8, 0.8] means:
left edge at 10% of the figure width
bottom edge at 10% of the figure height
axes width equal to 80% of the figure width
axes height equal to 80% of the figure height
fig = plt.figure(figsize=(4,3)) ### 1. create an empty figure
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8]) ### 2. add one axes using normalized coordinates
While slightly more involved, add_axes() gives you precise control over where each axes sits in the figure. That makes it a good choice for inset plots and manually arranged layouts.
x = np.linspace(0, 10, 50) ### start, stop, number of points
y = np.sin(x)
fig = plt.figure(figsize=(4,3)) ### create empty canvas on the figure (object)
### add two axes to the figure
axes1 = fig.add_axes([0.1, 0.1, 0.8, 0.8]) ### main axes
axes2 = fig.add_axes([0.2, 0.5, 0.4, 0.3]) ### insert axes
### larger figure Axes 1
axes1.plot(x, y, 'b')
axes1.set_xlabel('X_label_axes1')
axes1.set_ylabel('Y_label_axes1')
axes1.set_title('Axes 1 Title')
### insert figure Axes 2
axes2.plot(y, x, 'r')
axes2.set_xlabel('X_label_axes2')
axes2.set_ylabel('Y_label_axes2')
axes2.set_title('Axes 2 Title')
Text(0.5, 1.0, 'Axes 2 Title')
### Exercise: Figure with Main Plot and Inset using plt.figure()
# 1. Create a figure with figsize=(4, 3).
# 2. Add a main axes at [0.1, 0.1, 0.8, 0.8] and plot x vs x**2 in blue.
# Set the title to "Main: x squared".
# 3. Add an inset axes at [0.55, 0.15, 0.3, 0.3] and plot x vs x**3 in red.
# Set the title to "Inset: x cubed".
# (x = np.linspace(0, 5, 50) is already defined above.)
### Your code starts here.
### Your code ends here.
Text(0.5, 1.0, 'Inset: x cubed')
6.7.1. DPI#
dpisets dots per inch, which affects rendered resolution.
fig = plt.figure(figsize=(3,1), dpi=50)
axes = fig.add_axes([0.1, 0.1, 0.8, 0.8])
axes.plot(x, y, 'r')
axes.set_xlabel('x')
axes.set_ylabel('y')
axes.set_title('title')
Text(0.5, 1.0, 'title')
fig = plt.figure(figsize=(3,1), dpi=100)
axes = fig.add_axes([0.1, 0.1, 0.8, 0.8])
axes.plot(x, y, 'r')
axes.set_xlabel('x')
axes.set_ylabel('y')
axes.set_title('title')
Text(0.5, 1.0, 'title')
### Exercise: Setting Figure Size and DPI
# 1. Create a figure with figsize=(4, 3) and dpi=150.
# 2. Add axes using fig.add_axes([0.1, 0.1, 0.8, 0.8]).
# 3. Plot x vs x**2 with a green line.
# 4. Set the title to "High-Resolution Plot".
# (x is already defined above.)
### Your code starts here.
### Your code ends here.
Text(0.5, 1.0, 'High-Resolution Plot')
6.7.2. Recap#
A practical way to choose among the main Matplotlib workflows is:
Use
plt.plot()for quick, one-off exploration.Use
plt.subplots()for most plotting tasks.Use
fig.add_axes()when you need manual placement or inset axes.