Embedding high-quality plots directly in your LaTeX document ensures consistent fonts, seamless version control, and resolution-independent graphics. While many users export from Python or MATLAB to PDF, the pgfplots
package (built on PGF/TikZ) lets you script plots in pure LaTeX—fully integrated with your typesetting environment. In this post, we’ll explore eight practical techniques—from minimal setup and axis styling to advanced 3D surfaces, custom colormaps, animation in Beamer, and externalization for faster compiles. Each section shows a “before” snippet illustrating the pain of external images, followed by an “after” PGFPlots example you can copy, paste, and adapt. By the end, you’ll be able to generate publication-ready figures without leaving your .tex
source.
This guide is aimed at LaTeX users comfortable with basics but eager to master PGFPlots. We’ll cover: 1) minimal package setup, 2) axis customization, 3) plotting external CSV data, 4) defining custom colormaps, 5) 3D surface plotting, 6) logarithmic and parametric plots, 7) simple Beamer animations, and 8) externalizing figures for speed. Ready-to-use code snippets mean you spend less time wrestling with images and more time analyzing your data.
The Problem: Including plots as PDFs breaks font consistency and requires extra export steps.
Before (External PDF):
\begin{figure}
\centering
\includegraphics[width=0.8\linewidth]{plot.pdf}
\caption{Data curve.}
\end{figure}
After (PGFPlots Inline):
\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=1.18}
\begin{document}
\begin{figure}
\centering
\begin{tikzpicture}
\begin{axis}[
xlabel={Time (s)},
ylabel={Amplitude},
grid=major,
width=0.8\linewidth
]
\addplot[smooth] {sin(deg(x))};
\addlegendentry{sin(x)}
\end{axis}
\end{tikzpicture}
\caption{Inline sine curve.}
\end{figure}
\end{document}
Explanation: With \usepackage{pgfplots}
and \pgfplotsset{compat=1.18}
, you can define an axis
environment directly in LaTeX. Options like xlabel
, ylabel
, and grid=major
live alongside your text, ensuring uniform fonts and styles.
The Problem: Manually drawing ticks or shading regions in external tools is tedious and error-prone.
Before (Manual TikZ Tweaks):
% draw axes and ticks by hand in TikZ → verbose
\begin{tikzpicture}
\draw[->] (0,0) -- (5,0) node[right]{x};
\foreach \x in {1,2,3,4} \draw (\x,2pt) -- (\x,-2pt) node[below]{\x};
% ...
\end{tikzpicture}
After (axis
Options):
\begin{axis}[
xlabel={Length (m)},
ylabel={Force (N)},
xmin=0, xmax=10,
ymin=0, ymax=100,
xtick={0,2,4,6,8,10},
ytick distance=20,
tick align=outside,
legend pos=outer north east,
width=0.9\linewidth
]
\addplot[mark=*,blue] table {
0 0
2 20
4 50
6 80
8 90
10 100
};
\addlegendentry{Load}
\end{axis}
Explanation: Axis keys like xtick
, ytick distance
, and tick align
let you tailor ticks precisely. legend pos
places the legend automatically outside the plot area. No low-level TikZ hacking required.
The Problem: Copying data points into code is error-prone; external CSVs won’t match your document fonts.
Before (Manual Copy):
\addplot table {
x1 y1
x2 y2
...
};
After (table
Input from File):
\begin{axis}[xlabel=Epoch, ylabel=Accuracy (\%)]
\addplot table [col sep=comma, x=epoch, y=accuracy] {data/results.csv};
\addlegendentry{Model A}
\end{axis}
Explanation: Use table [col sep=comma]
to import CSV data directly. Reference column names (x=
, y=
) for clarity. Now your plots update when the CSV changes—no manual edits.
The Problem: Limited default palettes can make multi-series plots hard to distinguish.
Before (Default Colors):
\addplot table {...};
\addplot table {...};
\addplot table {...};
After (\pgfplotsset
Styles & \pgfplotscolormap
):
\pgfplotsset{
my cycle list/.style={
cycle list={
{blue,mark=*},
{red,mark=square*},
{green,mark=triangle*}
}
},
every axis/.append style={cycle list name=my cycle list}
}
\pgfplotscolormap{custom}{
rgb255(0cm)=(230,97,1);
rgb255(1cm)=(163,218,33);
rgb255(2cm)=(33,150,243)
}
\begin{axis}[colormap name=custom, colorbar]
\addplot3[surf] {exp(-x^2-y^2)};
\end{axis}
Explanation: cycle list
defines a reusable sequence of colors and markers for multiple plots. \pgfplotscolormap
creates custom gradients for surfaces or heatmaps. Both live in your preamble for consistency.
The Problem: Generating 3D graphics externally breaks perspective matching and requires additional software.
Before (External 3D Tool):
% export from MATLAB or Python → PDF inclusion
After (addplot3
Surf & Mesh):
\begin{axis}[
view={60}{30},
xlabel=$x$, ylabel=$y$, zlabel=$z$,
colormap/viridis, colorbar
]
\addplot3[surf,domain=-2:2,domain y=-2:2] {x*exp(-x^2-y^2)};
\addplot3[mesh,domain=0:360,samples y=0] ({cos(x)}, {sin(x)}, {0});
\end{axis}
Explanation: view
sets azimuth and elevation angles. Combine surf
and mesh
in one axis for mixed representations. All 3D rendering happens natively in LaTeX.
The Problem: Log‐log or parametric plots often require manual scaling or external transformations.
Before (Transform Data Externally):
% compute log10(x), log10(y) in Python → plot
After (axis
Log Modes & parametric
):
\begin{axis}[
xmode=log, ymode=log,
xlabel={$x$}, ylabel={$y$},
title={Power Law}
]
\addplot {x^(-1.5)};
\end{axis}
\begin{axis}[parametric, domain=0:2*pi, samples=200]
\addplot ({cos(deg(x))},{sin(deg(x))});
\addlegendentry{Circle}
\end{axis}
Explanation: xmode=log
and ymode=log
handle logarithmic scaling automatically. The parametric
key lets you plot parametric curves without precomputing coordinates.
The Problem: Creating step-by-step reveal animations with external GIFs or videos is clunky.
Before (External Video):
% embed GIF → messes with PDF size
After (\only
Overlays & PGFPlots):
\begin{frame}{Incremental Plot}
\begin{tikzpicture}
\begin{axis}[xlabel={x}, ylabel={y}]
\only<1>{\addplot {sin(deg(x))};}
\only<2>{\addplot {sin(deg(x))}; \addplot {cos(deg(x))};}
\only<3>{\addplot {sin(deg(x))}; \addplot {cos(deg(x))}; \addplot {tan(deg(x))};}
\end{axis}
Explanation: Use Beamer’s overlay specifications (
\only<n>
) to add one plot at a time. All animations are vector-based and keep your PDF lightweight.
8. Externalizing and Caching Figures
The Problem: Large or complex plots slow down every compile pass in draft mode.
Before (Always Recompiling):
% drafts with many plots → slow PDF builds
After (
external
Library):
\usepackage{pgfplots}
\usepgfplotslibrary{external}
\tikzexternalize[prefix=figures/]
% In document:
\begin{tikzpicture}
\begin{axis}[…]
\addplot {…};
\end{axis}
\end{tikzpicture}
Explanation: The
external
library caches each TikZ/PGFPlots picture as a separate PDF in figures/
. Subsequent compiles skip regeneration unless the code changes, drastically reducing build times.
Why Native Plots Matter
Choosing PGFPlots over external graphics delivers key advantages:
Unified Fonts & Styles: All text in figures matches your document’s typography.
Version Control Friendly: Plots live in your .tex
files—easy diffs and collaboration.
Parameterizable & Reproducible: Tweak plot parameters directly in LaTeX macros.
Integrated Workflow: No switching between tools—compile once for both text and graphics.
Going Further with PGFPlots
To level up even more:
Explore the PGFPlots manual for advanced macros and libraries.
Combine with siunitx
for consistent unit formatting on axes.
Leverage luaLaTeX
for dynamic data processing within your document.
Use tikz-3dplot
or pgfplotstable
for specialized table-driven visuals.
Key Packages & Commands
pgfplots
+ compat=1.18
(core plotting)
\begin{axis}…\end{axis}
, \addplot
(plot commands)
\pgfplotsset
, \pgfplotscolormap
(styles & palettes)
table[col sep=…]
(external data import)
view
, surf
, mesh
(3D)
xmode=log
, parametric
(special scales)
tikzexternalize
(caching)
Beamer overlays
(\only
, \pause
) for animations