Appendix D: matplotlib Cheatsheet

A quick reference for the most common matplotlib operations. Every snippet uses the explicit object-oriented (fig/ax) interface, which is the recommended approach for any chart that goes beyond a one-liner.


The fig/ax Pattern

Always start here. The Figure is the canvas; the Axes is where data gets drawn.

import matplotlib.pyplot as plt
import numpy as np

# Single plot
fig, ax = plt.subplots(figsize=(8, 5))

# Multiple subplots (2 rows, 3 columns)
fig, axes = plt.subplots(2, 3, figsize=(14, 8))
ax = axes[0, 1]  # access row 0, column 1

# Unequal grid with GridSpec
from matplotlib.gridspec import GridSpec
fig = plt.figure(figsize=(10, 8))
gs = GridSpec(2, 3, figure=fig)
ax_big   = fig.add_subplot(gs[0, :])    # top row, full width
ax_left  = fig.add_subplot(gs[1, 0])    # bottom-left
ax_right = fig.add_subplot(gs[1, 1:])   # bottom-right, spans 2 cols

Common Plot Types

Line Plot

ax.plot(x, y, color="#1F77B4", linewidth=1.5, linestyle="-", label="Series A")
ax.plot(x, y2, color="#FF7F0E", linewidth=1.5, linestyle="--", label="Series B")

Bar Chart

# Vertical
ax.bar(categories, values, color="#2CA02C", edgecolor="white", width=0.6)

# Horizontal
ax.barh(categories, values, color="#D62728", edgecolor="white", height=0.6)

# Grouped bars
x_pos = np.arange(len(categories))
width = 0.35
ax.bar(x_pos - width/2, vals_a, width, label="Group A")
ax.bar(x_pos + width/2, vals_b, width, label="Group B")
ax.set_xticks(x_pos)
ax.set_xticklabels(categories)

Scatter Plot

ax.scatter(x, y, s=50, c=color_values, cmap="viridis",
           alpha=0.7, edgecolors="white", linewidth=0.5)

Histogram

ax.hist(data, bins=30, color="#9467BD", edgecolor="white", alpha=0.8)

# Overlapping histograms
ax.hist(data_a, bins=30, alpha=0.5, label="A")
ax.hist(data_b, bins=30, alpha=0.5, label="B")

Box Plot

bp = ax.boxplot([data_a, data_b, data_c], labels=["A", "B", "C"],
                patch_artist=True, widths=0.5)
for patch, color in zip(bp["boxes"], ["#1F77B4", "#FF7F0E", "#2CA02C"]):
    patch.set_facecolor(color)

Heatmap

im = ax.imshow(matrix, cmap="RdBu_r", aspect="auto", vmin=-1, vmax=1)
fig.colorbar(im, ax=ax, shrink=0.8)

Pie Chart

ax.pie(sizes, labels=labels, autopct="%1.1f%%",
       colors=["#1F77B4", "#FF7F0E", "#2CA02C", "#D62728"],
       startangle=90, wedgeprops={"edgecolor": "white"})
ax.set_aspect("equal")

Area / Fill

ax.fill_between(x, y_lower, y_upper, alpha=0.3, color="#1F77B4", label="Range")
ax.plot(x, y_mean, color="#1F77B4", label="Mean")

Titles, Labels, and Text

# Title and axis labels
ax.set_title("Chart Title", fontsize=14, fontweight="bold", pad=12)
ax.set_xlabel("X-axis Label", fontsize=11)
ax.set_ylabel("Y-axis Label", fontsize=11)

# Suptitle for multi-panel figures
fig.suptitle("Overall Figure Title", fontsize=16, fontweight="bold", y=0.98)

# Text annotation at a data point
ax.annotate("Peak", xy=(x_peak, y_peak), xytext=(x_peak + 1, y_peak + 5),
            fontsize=10, arrowprops=dict(arrowstyle="->", color="gray"))

# Freestanding text
ax.text(0.02, 0.95, "n = 1,042", transform=ax.transAxes,
        fontsize=9, verticalalignment="top", color="gray")

Legend

# Default (auto-placed)
ax.legend()

# Custom placement
ax.legend(loc="upper left", frameon=False, fontsize=10)

# Outside the plot area
ax.legend(bbox_to_anchor=(1.02, 1), loc="upper left", borderaxespad=0)
fig.subplots_adjust(right=0.8)  # make room

# Custom handles
from matplotlib.lines import Line2D
handles = [Line2D([0], [0], color=c, lw=2) for c in ["#1F77B4", "#FF7F0E"]]
ax.legend(handles, ["Series A", "Series B"])

Colors and Colormaps

# Named color
ax.plot(x, y, color="steelblue")

# Hex code
ax.plot(x, y, color="#E69F00")

# RGB tuple (0-1 range)
ax.plot(x, y, color=(0.2, 0.4, 0.6))

# Set default color cycle
plt.rcParams["axes.prop_cycle"] = plt.cycler(color=["#1F77B4", "#FF7F0E", "#2CA02C"])

# Access a colormap
cmap = plt.get_cmap("viridis")
color = cmap(0.5)  # returns RGBA tuple at the midpoint

Axis Formatting

# Limits
ax.set_xlim(0, 100)
ax.set_ylim(-10, 10)

# Ticks
ax.set_xticks([0, 25, 50, 75, 100])
ax.set_xticklabels(["0", "25", "50", "75", "100"], fontsize=9)
ax.tick_params(axis="both", which="major", labelsize=9, length=4)

# Format tick labels with a function
from matplotlib.ticker import FuncFormatter
ax.yaxis.set_major_formatter(FuncFormatter(lambda v, _: f"${v:,.0f}"))

# Log scale
ax.set_yscale("log")

# Invert axis
ax.invert_yaxis()

Grid and Spines

# Light grid
ax.grid(True, axis="y", linestyle="--", linewidth=0.5, alpha=0.5)

# Remove top and right spines (recommended default)
ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)

# Remove all spines
for spine in ax.spines.values():
    spine.set_visible(False)

# Move bottom spine
ax.spines["bottom"].set_position(("data", 0))

Saving Figures

# PNG for screen (default)
fig.savefig("chart.png", dpi=150, bbox_inches="tight", facecolor="white")

# High-resolution PNG for print
fig.savefig("chart_print.png", dpi=300, bbox_inches="tight")

# Vector formats for publication
fig.savefig("chart.pdf", bbox_inches="tight")
fig.savefig("chart.svg", bbox_inches="tight")

# Transparent background
fig.savefig("chart.png", dpi=150, bbox_inches="tight", transparent=True)

Style Sheets

# Use a built-in style
plt.style.use("seaborn-v0_8-whitegrid")

# Stack styles
plt.style.use(["seaborn-v0_8-whitegrid", "presentation"])

# Temporary style context
with plt.style.context("ggplot"):
    fig, ax = plt.subplots()
    ax.plot(x, y)

# List all available styles
print(plt.style.available)

rcParams Quick Reference

Override defaults globally before creating any figures:

plt.rcParams.update({
    "figure.figsize":       (8, 5),
    "figure.dpi":           150,
    "axes.titlesize":       14,
    "axes.labelsize":       12,
    "axes.spines.top":      False,
    "axes.spines.right":    False,
    "lines.linewidth":      1.5,
    "font.family":          "sans-serif",
    "font.sans-serif":      ["Helvetica", "Arial", "DejaVu Sans"],
    "legend.frameon":       False,
    "savefig.bbox":         "tight",
    "savefig.dpi":          300,
})

Useful Patterns

Add a Horizontal or Vertical Reference Line

ax.axhline(y=0, color="gray", linewidth=0.8, linestyle="--")
ax.axvline(x=threshold, color="red", linewidth=0.8, linestyle=":")

Shade a Region

ax.axvspan(xmin=recession_start, xmax=recession_end, alpha=0.15, color="gray")

Secondary Y-Axis

ax2 = ax.twinx()
ax2.plot(x, y2, color="#D62728")
ax2.set_ylabel("Secondary Metric")

Tight Layout (Prevent Overlapping Labels)

fig.tight_layout()
# Or use constrained_layout at creation:
fig, ax = plt.subplots(figsize=(8, 5), constrained_layout=True)