matplotlib 3.11.0
Overview
Matplotlib is Python's foundational plotting library. It provides two interfaces:
- pyplot (state-based) —
plt.plot(),plt.show(). MATLAB-like, convenient for interactive work and quick scripts. - Object-oriented (OO) —
fig, ax = plt.subplots(); ax.plot(). Explicit control over every element. Preferred for complex plots and production code.
The core hierarchy is: Figure → Axes → Artist (lines, patches, text, images). Most pyplot functions are thin wrappers around Axes methods.
Usage
Quick start (pyplot)
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
plt.plot(x, np.sin(x), label='sin')
plt.xlabel('x'); plt.ylabel('y')
plt.legend(); plt.tight_layout()
plt.savefig('plot.png', dpi=150)
plt.show()
Object-oriented (preferred for complex plots)
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots(figsize=(8, 4))
ax.plot(x, np.sin(x), label='sin')
ax.plot(x, np.cos(x), label='cos')
ax.set_xlabel('x'); ax.set_ylabel('y')
ax.legend(); fig.tight_layout()
fig.savefig('plot.png', dpi=150, bbox_inches='tight')
Multiple subplots
# Regular grid
fig, axes = plt.subplots(2, 3, figsize=(12, 8), sharex=True)
# Named layout (preferred for irregular grids)
fig, axd = plt.subplot_mosaic([
['top_left', 'top_right'],
['bottom', 'bottom'],
], figsize=(10, 6))
# Constrained layout (auto-adjusts spacing)
fig, axes = plt.subplots(2, 2, constrained_layout=True)
Key OO methods on Axes
| Task | Method |
|---|---|
| Line plot | ax.plot(x, y, label='...', color='C0', linewidth=2) |
| Scatter | ax.scatter(x, y, c=colors, s=sizes, cmap='viridis') |
| Bar chart | ax.bar(x, height, width=0.8, color='steelblue') |
| Horizontal bar | ax.barh(y, width, left=None) |
| Histogram | ax.hist(data, bins=30, density=False, alpha=0.7) |
| Fill between | ax.fill_between(x, y1, y2, alpha=0.3) |
| Error bars | ax.errorbar(x, y, yerr=err, capsize=4) |
| Box plot | ax.boxplot(data, patch_artist=True) |
| Violin plot | ax.violinplot(data) |
| Pie chart | ax.pie(sizes, labels=labels, autopct='%.1f%%') |
| Heatmap | ax.imshow(Z, cmap='viridis', aspect='auto') |
| Contour | ax.contour(X, Y, Z, levels=10) / ax.contourf(...) |
| Pcolormesh | ax.pcolormesh(X, Y, Z, shading='auto', cmap='viridis') |
| Stem plot | ax.stem(x, y, linefmt='C0-', markerfmt='o') |
| Quiver (vector) | ax.quiver(x, y, u, v) |
| Streamplot | ax.streamplot(X, Y, U, V) |
| Hexbin | ax.hexbin(x, y, C, gridsize=20, cmap='Blues') |
| Text | ax.text(x, y, 'label', fontsize=12) |
| Annotate | ax.annotate('text', xy=(x,y), xytext=(tx,ty), arrowprops=dict(...)) |
| Title | ax.set_title('Title', fontsize=14, fontweight='bold') |
| Labels | ax.set_xlabel('X'); ax.set_ylabel('Y') |
| Limits | ax.set_xlim(0, 10); ax.set_ylim(-1, 1) |
| Scale | ax.set_xscale('log'); ax.set_yscale('symlog') |
| Ticks | ax.set_xticks([0, 5, 10]); ax.set_xticklabels(['a','b','c']) |
| Grid | ax.grid(True, alpha=0.3) |
| Legend | ax.legend(loc='upper right', framealpha=0.9) |
| Twin axis | ax2 = ax.twinx() |
Gotchas
plt.plot()without explicit axes draws on the "current" axes, which can silently target the wrong subplot in multi-figure scripts. Always usefig, ax = plt.subplots()for reliability.imshowvspcolormesh:imshowmaps array indices to pixel centers (default origin='upper'), whilepcolormeshmaps to grid corners. For heatmaps with labeled axes,pcolormeshis usually more intuitive. Useshading='auto'onpcolormeshfor correct alignment.- Colormap normalization: If colors look wrong, check that
vmin/vmaxare set explicitly. Without them, matplotlib auto-scales to data min/max which can be misleading when comparing multiple plots. tight_layout()vsconstrained_layout:tight_layout()runs once at call time;constrained_layout=True(orlayout='constrained') is reactive and adjusts as elements are added. Preferconstrained_layoutfor complex figures.- Backend selection must happen before any figure creation. Call
matplotlib.use('Agg')or setMPLBACKEND=Aggbefore importing pyplot if running headless (no display). - DPI confusion:
figsizeis in inches,savefig(dpi)controls output resolution. A 6×4 inch figure at 100 dpi = 600×400 pixels. For publication, usedpi=300orbbox_inches='tight'. - Legend overlaps data: Use
loc='best'for auto-placement, orbbox_to_anchor=(x, y)withlocto position outside the axes area. - Shared axes:
sharex=True/sharey=Trueinsubplots()links axis limits and removes redundant tick labels. But callingax.set_xlim()on one shared axis affects all of them. - Markers are not clipped by default — large markers can extend beyond axis boundaries. Use
clip_on=Trueor adjust margins withax.margins(x=0.05, y=0.05).
References
Detailed topic guides loaded on demand:
- 01-core-api — Figure/Axes/Artist hierarchy, pyplot vs OO, backends
- 02-plot-types — Line, scatter, bar, histogram, area, errorbar, stem, pie
- 03-layout — subplots, gridspec, subplot_mosaic, constrained_layout
- 04-colors-and-colormaps — Color specs, colormaps, normalization, color sequences
- 05-text-and-annotations — Text, titles, labels, annotations, math text, fonts
- 06-ticks-and-axes — Locators, formatters, scales, spines, twin axes
- 07-legend-and-colorbar — Legends, colorbars, custom handles
- 08-patches-and-shapes — Rectangle, Circle, Polygon, Arrow, FancyBboxPatch
- 09-transforms — Coordinate systems, Affine2D, blitting
- 10-styling-and-themes — rcParams, style.use(), contexts, custom styles
- 11-dates-and-times — Date plotting, locators, formatters, timezones
- 12-image-and-contour — imshow, pcolormesh, contour, quiver, streamplot
- 13-animation-and-widgets — FuncAnimation, widgets (Slider, Button, Cursor)
- 14-saving-and-exporting — savefig formats, DPI, vector vs raster, PDF/SVG