Matplotlib Cheat Sheet
Last updated
Figure and axes
A figure is the whole image. An axes is one plot inside it, and almost every call below is a method on ax.
| Task | Code |
|---|---|
| Import pyplot | import matplotlib.pyplot as plt |
| One figure with one plot | fig, ax = plt.subplots() |
| Set the size in inches | fig, ax = plt.subplots(figsize=(8, 4)) |
| Draw on the axes | ax.plot(x, y) |
| Show the figure | plt.show() |
| Save as a sharp PNG | fig.savefig("chart.png", dpi=150, bbox_inches="tight") |
| Save as vector graphics | fig.savefig("chart.svg"), fig.savefig("chart.pdf") |
| Transparent background | fig.savefig("chart.png", transparent=True) |
| Close a figure to free memory | plt.close(fig) |
| Quick pyplot style for one chart | plt.plot(x, y)
plt.title("Quick look")
plt.show() |
Plot types
| Task | Code |
|---|---|
| Line chart | ax.plot(x, y) |
| Scatter plot | ax.scatter(x, y, s=20, alpha=0.7) |
| Scatter colored by value, with a color bar | points = ax.scatter(x, y, c=y, cmap="viridis")
fig.colorbar(points, ax=ax) |
| Bar chart | ax.bar(cats, a) |
| Horizontal bar chart | ax.barh(cats, a) |
| Stacked bars | ax.bar(cats, a, label="2025")
ax.bar(cats, b, bottom=a, label="2026") |
| Grouped bars | pos = np.arange(len(cats))
ax.bar(pos - 0.2, a, width=0.4)
ax.bar(pos + 0.2, b, width=0.4)
ax.set_xticks(pos, labels=cats) |
| Histogram | ax.hist(data, bins=30) |
| Box plot | ax.boxplot([data, data * 2], tick_labels=["A", "B"]) |
| Violin plot | ax.violinplot([data, data * 2]) |
| Pie chart | ax.pie([40, 35, 25], labels=cats, autopct="%1.0f%%") |
| Band between two curves | ax.fill_between(x, y - 0.2, y + 0.2, alpha=0.3) |
| Error bars | ax.errorbar([1, 2, 3], [4, 5, 3], yerr=[0.5, 0.3, 0.6], fmt="o", capsize=4) |
| Step chart | ax.step(x, y, where="mid") |
| Heatmap of a 2D array | image = ax.imshow(np.random.default_rng(0).random((5, 5)), cmap="magma")
fig.colorbar(image, ax=ax) |
| Filled contour plot | X, Y = np.meshgrid(x, x)
ax.contourf(X, Y, np.sin(X) * np.cos(Y), levels=20) |
| Density of many points | ax.hexbin(data, data + np.random.default_rng(1).normal(size=200), gridsize=20) |
| Horizontal or vertical reference line | ax.axhline(0, color="gray", linestyle="--"), ax.axvline(5) |
| Shade a range | ax.axvspan(2, 4, alpha=0.2) |
Lines, markers and colors
| Task | Code |
|---|---|
| Color, width and line style | ax.plot(x, y, color="tab:red", linewidth=2, linestyle="--") |
| Markers on the points | ax.plot(x, y, marker="o", markersize=4) |
| Short format string | ax.plot(x, y, "g--o") |
| Transparency | ax.plot(x, y, alpha=0.5) |
| Line styles | "-", "--", "-.", ":" |
| Marker codes | "o", "s", "^", "x", ".", "*" |
| Ways to name a color | "tab:blue", "C1", "#1f77b4", (0.2, 0.4, 0.6) |
| n colors from a colormap | colors = plt.colormaps["viridis"](np.linspace(0, 1, 5)) |
| Your own color cycle | ax.set_prop_cycle(color=["#0b7285", "#e8590c", "#5f3dc4"]) |
| Outlined and hatched bars | ax.bar(cats, a, color="white", edgecolor="black", hatch="//") |
Titles, labels and legends
| Task | Code |
|---|---|
| Title and axis labels | ax.set_title("Sales"), ax.set_xlabel("Month"), ax.set_ylabel("EUR") |
| All of them in one call | ax.set(title="Sales", xlabel="Month", ylabel="EUR") |
| Legend from line labels | ax.plot(x, y, label="sin")
ax.legend() |
| Legend position and columns | ax.legend(loc="upper right", ncols=2, frameon=False) |
| Legend outside the plot | ax.legend(loc="center left", bbox_to_anchor=(1, 0.5)) |
| Text at a data position | ax.text(5, 0.5, "note") |
| Annotation with an arrow | ax.annotate("peak", xy=(1.57, 1), xytext=(3, 1.2), arrowprops=dict(arrowstyle="->")) |
| Value labels on bars | bars = ax.bar(cats, a)
ax.bar_label(bars) |
| Title for the whole figure | fig.suptitle("Q1 report") |
| Math in labels | ax.set_xlabel(r"$\alpha$ (rad)") |
Axes, ticks and scales
| Task | Code |
|---|---|
| Axis limits | ax.set_xlim(0, 10), ax.set_ylim(bottom=0) |
| Log scale | ax.set_yscale("log") |
| Choose ticks and their labels | ax.set_xticks([0, 5, 10], labels=["start", "middle", "end"]) |
| Rotate tick labels | ax.tick_params(axis="x", labelrotation=45) |
| Grid lines | ax.grid(True, alpha=0.3) |
| Percent axis | from matplotlib.ticker import PercentFormatter
ax.yaxis.set_major_formatter(PercentFormatter(1.0)) |
| Thousands separator | ax.yaxis.set_major_formatter("{x:,.0f}") |
| Hide the top and right border | ax.spines[["top", "right"]].set_visible(False) |
| Second y-axis on the right | ax2 = ax.twinx()
ax2.plot(x, y * 100, color="tab:orange") |
| Same scale on both axes | ax.set_aspect("equal") |
| Flip an axis | ax.invert_yaxis() |
| Hide the axes completely | ax.axis("off") |
| Readable date labels | fig.autofmt_xdate() |
Subplots and layout
plt.subplots(rows, cols) returns a NumPy array of axes. Index it like an array.
| Task | Code |
|---|---|
| Grid of plots | fig, axs = plt.subplots(2, 2, figsize=(8, 6)) |
| Draw on one of them | axs[0, 1].plot(x, y) |
| Loop over all of them | for ax in axs.flat:
ax.grid(True) |
| Share an axis between plots | fig, axs = plt.subplots(1, 3, sharey=True) |
| Spacing that avoids overlaps | fig, axs = plt.subplots(2, 2, layout="constrained") |
| Fix overlaps after drawing | fig.tight_layout() |
| Columns of different widths | fig, axs = plt.subplots(1, 2, width_ratios=[3, 1]) |
| Named layout with a wide panel | fig, axd = plt.subplot_mosaic([["top", "top"], ["left", "right"]])
axd["top"].plot(x, y) |
| Small plot inside a plot | inset = ax.inset_axes([0.6, 0.6, 0.35, 0.35]) |
| Hide an empty panel | axs[0].axis("off") |
Styles and defaults
| Task | Code |
|---|---|
| Use a built-in style | plt.style.use("ggplot") |
| List the styles | plt.style.available |
| Seaborn look without seaborn | plt.style.use("seaborn-v0_8-whitegrid") |
| Style for one figure only | with plt.style.context("dark_background"):
fig, ax = plt.subplots() |
| Default font size | plt.rcParams["font.size"] = 12 |
| Default figure size and resolution | plt.rcParams["figure.figsize"] = (8, 4), plt.rcParams["figure.dpi"] = 120 |
| Back to the defaults | plt.style.use("default") |
| Common colormaps: sequential, diverging, gray | "viridis", "coolwarm", "Greys" |
Plot from pandas
pandas plots with Matplotlib. Pass ax= to draw into your own axes, or keep the ax that pandas returns.
| Task | Code |
|---|---|
| DataFrame columns into your axes | df.plot(x="month", y="sales", ax=ax) |
| Bar chart of a group summary | df.groupby("city")["sales"].sum().plot.bar(ax=ax) |
| Keep styling what pandas drew | ax = df.plot(x="month", y="sales")
ax.set_title("Sales") |
| Columns straight into Matplotlib | ax.plot(df["month"], df["sales"]) |
Matplotlib 3.11: old forms and what to write now
Code copied from older tutorials can fail or warn in Matplotlib 3.11. Write the forms in the Matplotlib 3.11 column instead.
| Task | Matplotlib 3.11 | Old form |
|---|---|---|
| Box plot labels | ax.boxplot([data, data * 2], tick_labels=["A", "B"]) | labels=["A", "B"] |
| Horizontal box or violin plot | ax.boxplot(data, orientation="horizontal") | vert=False |
| Get a colormap | plt.colormaps["viridis"] | plt.cm.get_cmap("viridis") |
| Seaborn style | plt.style.use("seaborn-v0_8") | plt.style.use("seaborn") |
The Matplotlib code you need to turn data into a clear chart, grouped by task: figure and axes, plot types, lines and colors, titles and legends, axes and ticks, subplots and layout, styles, and plotting from pandas. Each row is a short snippet you can paste, plus one line on what it does.
Everything here uses the object-oriented style (fig, ax = plt.subplots(), then methods on ax) and is written for Matplotlib 3.11, the version Coddy runs. Older forms such as labels= in boxplot appear only in the last table, next to what to write instead. The examples use x = np.linspace(0, 10, 50), y = np.sin(x) and a sample of normal values called data. New to Python itself? Start with the Python cheat sheet, and keep the pandas, NumPy and scikit-learn cheat sheets next to this one.
Matplotlib cheat sheet FAQ
Is this Matplotlib cheat sheet free?
What is the difference between plt and ax?
plt.plot() draws on whatever axes is current, which is quick for a single chart. fig, ax = plt.subplots() gives you the figure and axes as objects, so ax.plot() always draws exactly where you mean. Use the ax style for anything with more than one plot, and for code you will keep.How do I change the figure size?
figsize in inches when you create the figure: fig, ax = plt.subplots(figsize=(10, 5)). To change the default for every figure, set plt.rcParams["figure.figsize"] = (10, 5). The pixel size of a saved file is figsize times dpi.How do I save a chart in high resolution?
fig.savefig("chart.png", dpi=300, bbox_inches="tight"). A higher dpi gives a sharper PNG, and bbox_inches="tight" trims empty margins. For print or slides, save as SVG or PDF, which stay sharp at any size.Why do my subplot titles and labels overlap?
layout="constrained", as in plt.subplots(2, 2, layout="constrained"), and Matplotlib makes room for titles, labels and color bars. On an existing figure, call fig.tight_layout() after drawing.Which Matplotlib version does this cheat sheet cover?
labels= in boxplot (now tick_labels=) and plt.cm.get_cmap (now plt.colormaps[...]), are in the last table next to what to write instead.