skip to content

matplotlib β€” Plotting

Create publication-quality 2-D plots with matplotlib. Covers pyplot basics, subplots, savefig, common chart types, and the show-vs-save pitfall.

3 min read 7 snippets yesterday intermediate

matplotlib β€” Plotting#

What it is#

matplotlib is the foundational Python plotting library. It produces static, animated, or interactive figures in PNG, PDF, SVG, and more. Most higher-level visualization libraries (seaborn, pandas .plot(), plotly) wrap or are inspired by matplotlib.

Install#

pip install matplotlib

Quick example#

import matplotlib.pyplot as plt

x = [1, 2, 3, 4, 5]
y = [2, 4, 3, 5, 4]

plt.plot(x, y, marker="o", color="steelblue")
plt.title("Simple Line Plot")
plt.xlabel("x")
plt.ylabel("y")
plt.tight_layout()
plt.savefig("line.png", dpi=150)
print("Saved line.png")

Output:

Saved line.png

[!NOTE] The plot itself is a PNG file. The image shows a connected line with circular markers at each data point.

When / why to use it#

  • Generating charts for reports, notebooks, or CI artifacts.
  • Fine-grained control over every visual element (fonts, tick marks, annotations).
  • When you need reproducible figures saved to disk rather than interactive browser charts.

Common pitfalls#

[!WARNING] plt.show() vs plt.savefig() β€” in non-interactive scripts, calling plt.show() blocks execution until you close the window. In headless environments (CI, Docker) it may crash. Use plt.savefig() and avoid plt.show() in scripts.

[!WARNING] Figure accumulation β€” calling plt.plot() without plt.figure() or plt.clf() accumulates lines on the same axes across loop iterations. Call plt.figure() at the start of each chart or use the OO interface.

[!TIP] The object-oriented interface (fig, ax = plt.subplots()) is clearer for complex figures and avoids the global state issues of the plt.* convenience functions.

Richer example β€” subplots with OO interface#

import matplotlib.pyplot as plt
import numpy as np

rng = np.random.default_rng(42)

fig, axes = plt.subplots(1, 2, figsize=(10, 4))

# Left: trig functions
x = np.linspace(0, 2 * np.pi, 200)
axes[0].plot(x, np.sin(x), label="sin", linewidth=2)
axes[0].plot(x, np.cos(x), label="cos", linestyle="--", linewidth=2)
axes[0].set_title("Trig functions")
axes[0].set_xlabel("radians")
axes[0].legend()
axes[0].grid(True, alpha=0.3)

# Right: scatter
axes[1].scatter(rng.standard_normal(50), rng.standard_normal(50),
                alpha=0.6, c="coral", edgecolors="k", linewidths=0.5)
axes[1].set_title("Random scatter (n=50)")
axes[1].set_xlabel("x")
axes[1].set_ylabel("y")

plt.tight_layout()
plt.savefig("subplots.png", dpi=150, bbox_inches="tight")
print("Saved subplots.png")

Output:

Saved subplots.png

[!NOTE] The output PNG shows two side-by-side panels: a smooth sine/cosine wave plot on the left and a scatter cloud on the right.

Common chart types#

import matplotlib.pyplot as plt
import numpy as np

fig, axs = plt.subplots(2, 2, figsize=(10, 8))

# Bar chart
categories = ["A", "B", "C", "D"]
values = [23, 45, 12, 67]
axs[0, 0].bar(categories, values, color="steelblue")
axs[0, 0].set_title("Bar chart")

# Histogram
data = np.random.default_rng(0).standard_normal(500)
axs[0, 1].hist(data, bins=30, edgecolor="white")
axs[0, 1].set_title("Histogram")

# Pie chart
axs[1, 0].pie([40, 30, 20, 10], labels=categories, autopct="%1.0f%%")
axs[1, 0].set_title("Pie chart")

# Heatmap
matrix = np.random.default_rng(1).random((5, 5))
im = axs[1, 1].imshow(matrix, cmap="viridis")
fig.colorbar(im, ax=axs[1, 1])
axs[1, 1].set_title("Heatmap")

plt.tight_layout()
plt.savefig("chart_types.png", dpi=120)
print("Saved chart_types.png")

Output:

Saved chart_types.png