Python Charts

Python plotting and visualization demystified

Format Text with LaTeX Equations in Matplotlib Labels

Use LaTeX math notation in Matplotlib titles, axis labels, legends, and annotations with raw strings and mathtext.

TL;DR

Wrap any label string in a raw string and use $...$ for math:

ax.set_title(r'$f(x) = \sin(x)$')
ax.set_xlabel(r'$x$ (radians)')
ax.set_ylabel(r'$f(x)$')

Matplotlib sine wave with LaTeX axis labels

How it works

Matplotlib ships with its own math rendering engine called mathtext — no external LaTeX installation needed. You activate it by placing your expression between dollar signs inside a raw Python string (prefix r).

The r prefix matters: it stops Python from interpreting backslashes like \n or \t before Matplotlib sees them.

# Without r-prefix: \sin is treated as \s + in -> wrong
ax.set_title('$f(x) = \sin(x)$')   # risky

# With r-prefix: backslash passed straight to mathtext -> correct
ax.set_title(r'$f(x) = \sin(x)$')  # always do this

Common math symbols

What you want Mathtext syntax
Greek letters \alpha, \beta, \sigma, \mu
Superscript x^{2}
Subscript x_{0}
Fraction \frac{a}{b}
Square root \sqrt{x}
Infinity \infty
Sum / integral \sum, \int

Titles and axis labels

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(-np.pi, np.pi, 200)
y = np.sin(x)

fig, ax = plt.subplots(figsize=(7, 4))
ax.plot(x, y)

ax.set_title(r'$f(x) = \sin(x)$', fontsize=16)
ax.set_xlabel(r'$x$ (radians)', fontsize=13)
ax.set_ylabel(r'$f(x)$', fontsize=13)

plt.tight_layout()
plt.show()

Legend entries

Pass the same raw-string syntax to the label argument:

ax.plot(x2, y_exp,   label=r'$f(x) = e^{-x}$')
ax.plot(x2, y_gauss, label=r'$g(x) = e^{-x^2}$')
ax.legend(fontsize=12)

Annotations

ax.annotate() and ax.text() accept mathtext too:

ax.annotate(
    r'$g(0) = 1$',
    xy=(0, 1), xytext=(0.5, 0.85),
    arrowprops=dict(arrowstyle='->', color='gray'),
    fontsize=12
)

Full example

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 4, 200)
y_exp   = np.exp(-x)
y_gauss = np.exp(-x**2)

fig, ax = plt.subplots(figsize=(7, 4))
ax.plot(x, y_exp,   label=r'$f(x) = e^{-x}$',   color='tab:orange', lw=2)
ax.plot(x, y_gauss, label=r'$g(x) = e^{-x^2}$', color='tab:green',  lw=2)

ax.annotate(
    r'$g(0) = 1$',
    xy=(0, 1), xytext=(0.5, 0.85),
    arrowprops=dict(arrowstyle='->', color='gray'),
    fontsize=12
)

ax.set_title(r'Decay Functions: $e^{-x}$ vs $e^{-x^2}$', fontsize=14)
ax.set_xlabel(r'$x$', fontsize=13)
ax.set_ylabel(r'$y$', fontsize=13)
ax.legend(fontsize=12)
ax.grid(True, linestyle='--', alpha=0.5)
plt.tight_layout()
plt.show()

Matplotlib decay functions with LaTeX legend and annotation

Mixing plain text and math

You can freely mix regular text and math in the same string:

ax.set_xlabel(r'Time $t$ (seconds)')
ax.set_title(r'Growth rate: $\mu = 0.42\ \mathrm{hr}^{-1}$')

Use \mathrm{...} for upright (roman) text inside a math block — useful for units.

Using a full LaTeX install (optional)

If mathtext is not enough, you can enable a full LaTeX renderer. This requires LaTeX and dvipng/dvisvgm installed on your system:

plt.rcParams.update({
    'text.usetex': True,
    'font.family': 'serif',
})

Only do this when you need features mathtext does not cover — it is slower and adds an external dependency.