Matplotlib Master Hub + Recipes





Matplotlib Master Hub + Recipes (Python) | Pythoneo






Matplotlib Master Hub + Recipes (Python)

Publication‑quality plotting with figures/axes, styles, subplots, annotations, legends/colorbars, time series, 3D, export, and performance.

Updated: 2025‑08‑20
Covers: Matplotlib 3.7 → 3.9+
License: CC BY 4.0
Start

Quickstart (Figure/Axes, Layout)

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 2*np.pi, 200)
y = np.sin(x)

fig, ax = plt.subplots(figsize=(6,4), layout="constrained")  # or tight_layout()
ax.plot(x, y, label="sin(x)")
ax.set(title="Sine Wave", xlabel="x (rad)", ylabel="amplitude")
ax.grid(True, alpha=.3)
ax.legend()
plt.show()
Prefer the object‑oriented API (fig, ax = plt.subplots). Use layout=”constrained” or tight_layout() to reduce clipping.
Theme

Styles & Themes (rcParams, style.use)

import matplotlib.pyplot as plt
plt.style.use("seaborn-v0_8")   # or "ggplot", "bmh", "classic", custom .mplstyle

# rcParams override
plt.rcParams.update({
  "figure.dpi": 110,
  "axes.spines.top": False, "axes.spines.right": False,
  "axes.titlesize": 14, "axes.labelsize": 12,
  "legend.frameon": False
})
Create a project‑wide .mplstyle and call style.use at entry. Keep typography consistent (font.family, size) for entire reports.
Basics

Line, Scatter, Bar, Area, Pie

Line & Scatter

fig, ax = plt.subplots()
ax.plot(x, np.sin(x), color="#2563eb", lw=2, label="sin")
ax.scatter(x[::10], np.sin(x)[::10], color="#10b981", s=25, zorder=3, label="samples")
ax.legend(); ax.set(xlabel="x", ylabel="y"); ax.grid(True, alpha=.2)

Bar

cats = ["A","B","C"]; vals = 
fig, ax = plt.subplots()
ax.bar(cats, vals, color="#2563eb")
for i,v in enumerate(vals): ax.text(i, v+0.5, str(v), ha="center")

Area (fill_between)

fig, ax = plt.subplots()
ax.plot(x, y, color="#2563eb"); ax.fill_between(x, 0, y, alpha=.2, color="#2563eb")

Pie / Donut

fig, ax = plt.subplots()
vals = ; labels = list("ABCD")
wedges, _ = ax.pie(vals, labels=labels, autopct="%1.0f%%", startangle=90)
# Donut
centre = plt.Circle((0,0), 0.60, fc="white")
ax.add_artist(centre); ax.set(aspect="equal")

Stat

Histogram, KDE, Box, Violin

Histogram + KDE

data = np.random.normal(0, 1, 1000)
fig, ax = plt.subplots()
ax.hist(data, bins=40, density=True, alpha=.5, color="#2563eb")
from scipy.stats import gaussian_kde
kde = gaussian_kde(data); xs = np.linspace(-4,4,400)
ax.plot(xs, kde(xs), color="#10b981", lw=2)

Box & Violin

fig, ax = plt.subplots()
ax.boxplot([np.random.randn(200), np.random.randn(200)+.5], labels=["A","B"])
ax.set(title="Boxplot")

Layout

Subplots & Gridspec

import matplotlib.gridspec as gs
fig = plt.figure(layout="constrained", figsize=(8,5))
grid = gs.GridSpec(2, 3, figure=fig)
ax1 = fig.add_subplot(grid[0, :])
ax2 = fig.add_subplot(grid)
ax3 = fig.add_subplot(grid[1, 1:])
ax1.plot(x, np.sin(x)); ax1.set_title("Top")
ax2.bar(["A","B","C"], ); ax2.set_title("Bottom Left")
ax3.plot(x, np.cos(x), color="#ef4444"); ax3.set_title("Bottom Right (wide)")
plt.show()
For simple grids, use fig, axes = plt.subplots(nrows, ncols, sharex/sharey). For complex layouts, prefer GridSpec.
Axes

Twin & Secondary Axes

fig, ax1 = plt.subplots()
ax2 = ax1.twinx()  # share x, separate y
ax1.plot(x, np.sin(x), color="#2563eb"); ax1.set_ylabel("Amplitude")
ax2.plot(x, np.cos(x), color="#10b981"); ax2.set_ylabel("Cosine")
# Secondary axis via transform
def f2c(F): return (F-32)*(5/9)
def c2f(C): return C*(9/5)+32
fig, ax = plt.subplots()
ax.plot(,)  # Celsius baseline
sec = ax.secondary_yaxis("right", functions=(c2f, f2c))
sec.set_ylabel("Fahrenheit")
Dual axes can confuse; label clearly and consider normalization instead. Use secondary axes for unit conversions, not different metrics.
Explain

Annotations, Arrows, Text

fig, ax = plt.subplots()
ax.plot(x, y)
peak_x = x[y.argmax()]; peak_y = y.max()
ax.annotate("Peak", xy=(peak_x, peak_y), xytext=(peak_x+.5, peak_y+.3),
            arrowprops=dict(arrowstyle="->", color="#111827"), fontsize=10,
            bbox=dict(boxstyle="round,pad=0.2", fc="#f3f4f6"))
ax.text(0.1, 0.9, "Note", transform=ax.transAxes, fontsize=10, color="#374151")
Use axis coordinates (transform=ax.transAxes) for layout‑stable labels. Wrap long text or reduce font sizes for small figures.
Guide

Legends & Colorbars

# Legend
fig, ax = plt.subplots()
ax.plot(x, np.sin(x), label="sin"); ax.plot(x, np.cos(x), label="cos")
ax.legend(loc="upper right", frameon=False)

# Colorbar
data = np.random.rand(30, 30)
im = ax.imshow(data, cmap="viridis")
cbar = fig.colorbar(im, ax=ax, orientation="vertical", shrink=.8)
cbar.set_label("Intensity")
For shared colorbars across subplots, create a dedicated axis via fig.add_axes([…]) and pass it to fig.colorbar(…, cax=cbar_ax).
Time

Dates & Time Series Formatting

import pandas as pd
import matplotlib.dates as mdates

ts = pd.date_range("2025-01-01", periods=120, freq="D")
y = pd.Series(np.sin(np.linspace(0, 6, 120)), index=ts).rolling(7, min_periods=1).mean()

fig, ax = plt.subplots(figsize=(7,4))
ax.plot(y.index, y.values)
ax.xaxis.set_major_locator(mdates.MonthLocator())
ax.xaxis.set_major_formatter(mdates.DateFormatter("%b %Y"))
fig.autofmt_xdate()
ax.set(title="Smoothed Trend", ylabel="Value"); ax.grid(True, alpha=.3)
Use pandas datetime index for convenience, then control ticks with matplotlib.dates locators and formatters. Call fig.autofmt_xdate() to rotate/align labels.
3D

3D Plots: Surface, Wireframe, Scatter

from mpl_toolkits.mplot3d import Axes3D  # noqa: F401
fig = plt.figure(figsize=(7,5))
ax = fig.add_subplot(111, projection="3d")
X = np.linspace(-3,3,60); Y = np.linspace(-3,3,60)
X, Y = np.meshgrid(X, Y); Z = np.sin(np.sqrt(X**2 + Y**2))
ax.plot_surface(X, Y, Z, cmap="viridis", linewidth=0, antialiased=True)
ax.set(title="3D Surface", xlabel="X", ylabel="Y", zlabel="Z")
3D in Matplotlib is CPU‑bound and not interactive like WebGL; keep grids small and consider Plotly for heavy interactive 3D.
Share

Export: SVG/PNG/PDF

fig = plt.gcf()
fig.savefig("figure.svg", bbox_inches="tight")          # vector for print
fig.savefig("figure.png", dpi=200, bbox_inches="tight") # raster for web
fig.savefig("figure.pdf", bbox_inches="tight")          # vector (PDF)
Prefer SVG/PDF for publications. Use transparent=True for overlays. Always set bbox_inches=”tight” to avoid clipped labels.
Speed

Performance Tips

  • Reduce points: downsample, plot summaries (means/CI), or use line simplification (rcParams[“path.simplify”]=True).
  • Avoid per‑point artists; use a single Line2D for large series and update data instead of re‑creating figures.
  • Turn off antialiasing where acceptable; limit alpha and markers for 100k+ points.
  • For animations, use FuncAnimation with blitting; pre‑allocate artists and update set_data.
  • Rasterize heavy collections: artist.set_rasterized(True) for vector outputs with large point clouds.
# Animation skeleton with blit
import matplotlib.animation as animation
fig, ax = plt.subplots(); ln, = ax.plot([], [], lw=2)
ax.set(xlim=(0,2*np.pi), ylim=(-1,1))
def init(): ln.set_data([], []); return ln,
def update(frame): 
    x = np.linspace(0, 2*np.pi, 400); y = np.sin(x+frame/10)
    ln.set_data(x, y); return ln,
ani = animation.FuncAnimation(fig, update, init_func=init, frames=200, blit=True)
Fix

Troubleshooting & FAQ

Labels clipped or overlapping

Use layout=”constrained” or tight_layout(); increase figure size; rotate tick labels.

Legend covers data

Set bbox_to_anchor and loc; reduce entries; place outside the axes when needed.

Too slow with many points

Downsample, remove markers, disable alpha, rasterize heavy layers, or switch to specialized plotting libs.

Fonts inconsistent across machines

Bundle a font or pin font.family in rcParams; avoid system‑dependent defaults.

PNG looks blurry

Increase dpi (e.g., 200–300) and avoid upscaling in CSS; prefer SVG for crispness.

Datetime ticks unreadable

Use matplotlib.dates locators/formatters; limit range; auto‑format with fig.autofmt_xdate().

FAQ

Object‑oriented vs pyplot? Use OO (fig, ax) for reusable, testable code; pyplot is fine for quick, one‑off scripts.

How to ensure consistent style in a team? Commit a .mplstyle file and load it via plt.style.use at program start.

When to use secondary axes? For unit conversions of the same underlying data; avoid mixing unrelated metrics on dual axes.

If this page helped, consider linking it under “Python Data Visualization,” “Matplotlib Recipes,” or “Analytics Engineering” resources. Sharing supports more free content like this.

© 2025 Pythoneo · Designed to be highly linkable: comprehensive, evergreen, copy‑paste friendly, with export and performance built‑in.