Fatskills
Practice. Master. Repeat.
Study Guide: TECH **Matplotlib Basics: Figure, Axes, Subplots, Styles**
Source: https://www.fatskills.com/introdution-to-engineering/chapter/tech-matplotlib-basics-figure-axes-subplots-styles

TECH **Matplotlib Basics: Figure, Axes, Subplots, Styles**

By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.

⏱️ ~8 min read

Matplotlib Basics: Figure, Axes, Subplots, Styles

A Hyper-Practical, Zero-Fluff Study Guide for Data Scientists


1. What This Is & Why It Matters

Matplotlib is the foundation of Python data visualization. If you’ve ever generated a plot in pandas (df.plot()), you’ve used Matplotlib under the hood. But when you need custom layouts, multiple subplots, or fine-grained styling, you must work directly with Matplotlib’s core objects: Figure and Axes.

Why This Matters in Production

  • Broken dashboards: If you don’t understand Figure vs. Axes, your plots will overlap, misalign, or fail to render in Jupyter/Streamlit.
  • Slow reports: Poorly structured subplots waste CPU cycles and memory, especially when generating hundreds of plots (e.g., in a batch ETL job).
  • Unprofessional outputs: Default styles look dated. Custom styles (fonts, colors, grids) make your work stand out in client presentations or internal reviews.

Real-World Scenario

You’re building a real-time monitoring dashboard for a logistics company. The dashboard must show: 1. A line plot of daily package volumes (2020–2024).
2. A bar plot of delivery delays by region.
3. A pie chart of shipping method distribution.

Problem: If you use plt.plot() for each chart, they’ll stack vertically in one figure, wasting space. If you use subplots incorrectly, the pie chart will stretch into an oval. Solution: Master Figure, Axes, and subplots to control layout precisely.


2. Core Concepts & Components

Concept Definition Production Insight
Figure The top-level container for all plot elements (like a canvas). If you don’t close figures (plt.close()), memory leaks in long-running scripts.
Axes The actual plotting area (where data is drawn). A Figure can have many. Misusing Axes leads to overlapping plots or incorrect scaling (e.g., log vs. linear).
Subplot A grid of Axes within a Figure. Poor subplot layouts waste screen space and confuse stakeholders.
plt.subplots() Creates a Figure and a grid of Axes in one call. Use this instead of plt.subplot() for cleaner code and better control.
tight_layout() Automatically adjusts subplot spacing to prevent label overlap. Always call this before saving figures to avoid cropped labels.
style Predefined visual themes (e.g., ggplot, seaborn). Default styles look unprofessional. Use plt.style.use('seaborn') for consistency.
savefig() Saves the Figure to a file (PNG, PDF, SVG). Always set dpi=300 for high-quality reports.
rcParams Global Matplotlib configuration (e.g., default font size). Override rcParams at the start of scripts to enforce team-wide styling.


3. Step-by-Step Hands-On: Build a Multi-Panel Dashboard


Prerequisites

  • Python 3.8+ with matplotlib and pandas installed: bash pip install matplotlib pandas
  • A dataset (we’ll use a synthetic one for this guide).

Task

Create a 3-panel dashboard with: 1. A line plot of daily sales (2020–2024).
2. A bar plot of sales by region.
3. A pie chart of product categories.


Step 1: Generate Synthetic Data

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# Generate synthetic data
np.random.seed(42)
dates = pd.date_range("2020-01-01", "2024-12-31", freq="D")
sales = np.cumsum(np.random.normal(100, 10, len(dates))) + 1000
regions = ["North", "South", "East", "West"]
region_sales = {r: np.random.randint(500, 2000) for r in regions}
categories = ["Electronics", "Clothing", "Furniture", "Groceries"]
category_sales = [35, 25, 20, 20]

# Create DataFrames
df_sales = pd.DataFrame({"Date": dates, "Sales": sales})
df_regions = pd.DataFrame({"Region": regions, "Sales": region_sales.values()})
df_categories = pd.DataFrame({"Category": categories, "Sales": category_sales})


Step 2: Create a Figure with Subplots

# Create a 2x2 grid of subplots (we'll use 3 of them)
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(12, 8))

# Flatten axes for easy iteration (axes is a 2x2 array)
axes = axes.flatten()

# Line plot (top-left)
axes[0].plot(df_sales["Date"], df_sales["Sales"], color="tab:blue")
axes[0].set_title("Daily Sales (2020–2024)")
axes[0].set_xlabel("Date")
axes[0].set_ylabel("Sales ($)")

# Bar plot (top-right)
axes[1].bar(df_regions["Region"], df_regions["Sales"], color="tab:orange")
axes[1].set_title("Sales by Region")
axes[1].set_ylabel("Sales ($)")

# Pie chart (bottom-left)
axes[2].pie(
df_categories["Sales"],
labels=df_categories["Category"],
autopct="%1.1f%%",
startangle=90,
colors=["tab:green", "tab:red", "tab:purple", "tab:brown"] ) axes[2].set_title("Sales by Category") # Hide the unused subplot (bottom-right) axes[3].axis("off") # Adjust layout to prevent overlap plt.tight_layout() # Save the figure plt.savefig("sales_dashboard.png", dpi=300, bbox_inches="tight") plt.show()


Expected Output

Sales Dashboard (Example output; actual plot will vary slightly.)


Step 3: Verify Success

  1. Check the saved file sales_dashboard.png:
    bash
    ls -lh sales_dashboard.png # Should be ~200–500 KB
  2. Open the file to confirm:
  3. No overlapping labels.
  4. Consistent font sizes.
  5. All 3 plots are visible.

4. ? Production-Ready Best Practices


Layout & Performance

  • Use plt.subplots() instead of plt.subplot(): Cleaner code and better control over Axes.
  • Close figures explicitly: In long-running scripts, call plt.close(fig) to free memory.
  • Set figsize early: Adjust figsize=(width, height) to match your output (e.g., (10, 6) for reports).
  • Use tight_layout(): Prevents label overlap. For fine control, use plt.subplots_adjust().

Styling

  • Enforce team-wide styles: Override rcParams at the start of scripts: python plt.rcParams.update({
    "font.size": 12,
    "axes.titlesize": 14,
    "axes.labelsize": 12,
    "xtick.labelsize": 10,
    "ytick.labelsize": 10,
    "figure.titlesize": 16,
    "figure.figsize": (10, 6) })
  • Use plt.style.use(): Apply consistent themes (e.g., seaborn, ggplot).
  • Avoid default colors: Use tab10 or custom palettes for accessibility.

Saving Figures

  • Always set dpi=300 for reports: Low DPI (default=100) looks pixelated.
  • Use bbox_inches="tight": Prevents cropped labels.
  • Prefer vector formats (PDF/SVG) for reports: Avoids pixelation when zooming.

Automation

  • Loop over subplots: For dynamic dashboards, use for ax in axes: to iterate.
  • Reuse figures: Clear axes with ax.clear() instead of creating new figures.


5. ⚠️ Common Mistakes & Traps

Mistake Symptom Fix/Prevention
Using plt.plot() for subplots All plots stack vertically in one figure. Use fig, axes = plt.subplots() and plot on axes[i].
Forgetting tight_layout() Axis labels overlap or get cropped. Call plt.tight_layout() before plt.show() or savefig().
Mixing plt and ax methods Plots appear in the wrong subplot or disappear. Stick to ax.plot(), ax.bar(), etc. (avoid plt.plot() in subplots).
Not setting figsize Plots are too small or too large for the output. Set figsize=(width, height) in plt.subplots().
Ignoring dpi in savefig() Saved images look pixelated in reports. Always use dpi=300 for high-quality outputs.
Overlapping pie chart labels Labels in pie charts overlap or get cut off. Use autopct and pctdistance to adjust label positions.


6. ? Exam/Certification Focus


Typical Question Patterns

  1. Subplot Layouts:
  2. "How do you create a 2x3 grid of subplots?"
    Answer: fig, axes = plt.subplots(2, 3, figsize=(12, 8)).
  3. "How do you hide an unused subplot?"
    Answer: axes[5].axis("off").

  4. Styling:

  5. "How do you apply the ggplot style to all plots?"
    Answer: plt.style.use("ggplot").
  6. "How do you set the default font size for all plots?"
    Answer: plt.rcParams["font.size"] = 12.

  7. Saving Figures:

  8. "How do you save a figure as a 300 DPI PNG?"
    Answer: plt.savefig("plot.png", dpi=300, bbox_inches="tight").

Key ⚠️ Trap Distinctions

  • plt.plot() vs. ax.plot():
  • plt.plot(): Works on the "current" figure/axes (unpredictable in subplots).
  • ax.plot(): Explicitly plots on a specific Axes object (recommended).
  • plt.subplots() vs. plt.subplot():
  • plt.subplots(): Creates all subplots at once (cleaner for grids).
  • plt.subplot(): Adds one subplot at a time (messy for complex layouts).

Scenario-Based Question

"You need to create a dashboard with 4 plots (2 rows, 2 columns). The bottom-right plot is unused. How do you hide it?" Answer:


fig, axes = plt.subplots(2, 2, figsize=(10, 8))
axes[1, 1].axis("off")  # Hide the bottom-right subplot


7. ? Hands-On Challenge


Challenge

Create a 2x2 subplot grid where: 1. Top-left: Line plot of y = sin(x) (0 to 2π).
2. Top-right: Scatter plot of y = cos(x) vs. x.
3. Bottom-left: Histogram of 1000 random normal values.
4. Bottom-right: Hide the subplot.

Constraints: - Use plt.subplots().
- Apply the seaborn style.
- Save the figure as trig_plots.png (300 DPI).


Solution

import numpy as np
import matplotlib.pyplot as plt

# Apply style
plt.style.use("seaborn")

# Create subplots
fig, axes = plt.subplots(2, 2, figsize=(10, 8))
x = np.linspace(0, 2 * np.pi, 100)

# Top-left: sin(x)
axes[0, 0].plot(x, np.sin(x), color="tab:blue")
axes[0, 0].set_title("sin(x)")

# Top-right: cos(x) scatter
axes[0, 1].scatter(x, np.cos(x), color="tab:orange", s=10)
axes[0, 1].set_title("cos(x)")

# Bottom-left: histogram
axes[1, 0].hist(np.random.normal(0, 1, 1000), bins=30, color="tab:green")
axes[1, 0].set_title("Normal Distribution")

# Hide bottom-right
axes[1, 1].axis("off")

# Adjust layout and save
plt.tight_layout()
plt.savefig("trig_plots.png", dpi=300, bbox_inches="tight")
plt.show()

Why It Works: - plt.subplots(2, 2) creates a 2x2 grid.
- axes[i, j] accesses subplots by row/column.
- axis("off") hides the unused subplot.
- tight_layout() prevents label overlap.


8. ? Rapid-Reference Crib Sheet

Command/Concept Usage Notes
plt.subplots(nrows, ncols) fig, axes = plt.subplots(2, 2) Returns Figure and Axes array.
ax.plot() ax.plot(x, y, color="red") Preferred over plt.plot() for subplots.
ax.set_title() ax.set_title("Sales") Sets title for a specific Axes.
plt.tight_layout() plt.tight_layout() Prevents label overlap. Call before savefig().
plt.style.use() plt.style.use("seaborn") Applies a style to all plots.
plt.savefig() plt.savefig("plot.png", dpi=300, bbox_inches="tight") Always set dpi and bbox_inches.
ax.axis("off") ax.axis("off") Hides an unused subplot.
plt.rcParams plt.rcParams["font.size"] = 12 Override default settings.
figsize figsize=(10, 6) Width x height in inches.
⚠️ Default DPI dpi=100 (low quality) Always set dpi=300 for reports.
⚠️ Subplot indexing axes[0, 1] (row 0, column 1) Starts at 0.
⚠️pltvs.axmethods Use ax.plot(), not plt.plot(), in subplots. plt.plot() works on the "current" axes (unpredictable).


9. ? Where to Go Next

  1. Matplotlib Official Tutorials – Start with "Pyplot" and "Subplots".
  2. Seaborn Gallery – See how Matplotlib is used under the hood in Seaborn.
  3. Python Data Science Handbook (Jake VanderPlas) – Chapter 4 covers Matplotlib in depth.
  4. Real Python – Matplotlib Guide – Practical examples and best practices.


ADVERTISEMENT