Matplotlib Master Hub + Recipes (Python)
Publication‑quality plotting with figures/axes, styles, subplots, annotations, legends/colorbars, time series, 3D, export, and performance.
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()
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
})
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")
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")
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()
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")
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")
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")
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)
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")
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)
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)
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.
© 2025 Pythoneo · Designed to be highly linkable: comprehensive, evergreen, copy‑paste friendly, with export and performance built‑in.