How do I make the axis labels use multiples of \pi
in PGFPlots?
4 Answers
As mentioned in the comments, this is basically the same as Pgfplots with custom axis markers. All you need to do is to specify where you want the xtick={...}
and how you want each of them labelled via xticklabels={...}
.
Method 1: Explicit Labels:
Explicit labels can be specified using xticklabels
.
The one complication that comes about is that sometimes the label overlaps with the plot as is the case for -\pi
and 2pi
in the blue graph. I have not found a elegant way to fix that so I just manually add some spacing to those labels to tweak them as I did the red graph:
Method 2: Scaled Axis Labels:
An alternate is to scale the x-axis labels in terms of multiples of pi
, and show that the x axis labels are multiples of pi
. This solution is based on Spikes solution, so you should up vote that if you prefer this version. I prefer to label this as part of the axis (brown graph), but others might prefer to display it as in the cyan graph:
xticklabels
:
If you want a tick mark, but not a corresponding label you can simply place an empty label as in $$
or just better just use a double comma ,,
to skip it being labelled. For instance, if the labels at +\pi
and -\pi
are not desired, simply replace those labels with spaces (extra spaces here are just to point out where the gap is):
xticklabels={$-2\pi$, $-\frac{3\pi}{2}$, , $-\frac{\pi}{2}$,
$\frac{\pi}{2}$, , $\frac{3\pi}{2}$, $2\pi$}
xtick
:
Note that two methods of specifying where the tick marks go are used in the code. One is to explicitly list them as
xtick={-6.28318, -4.7123889, -3.14159, -1.5708, 1.5708, 3.14159, 4.7123889, 6.28318}
This is used in the first two examples so that the correspondence between the xtick
and xticklabels
is easier to see. The second two use the more compact method:
xtick={-6.28318, -4.7123889, ..., 6.28318}
Code:
\documentclass{article}
\usepackage{pgfplots}
% Grouping the common style settings here to make the code below easier to read
\pgfkeys{/pgfplots/Axis Style/.style={
width=13.5cm, height=5cm,
axis x line=center,
axis y line=middle,
samples=100,
ymin=-1.5, ymax=1.5,
xmin=-7.0, xmax=7.0,
domain=-2*pi:2*pi
}}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
Axis Style,
xtick={
-6.28318, -4.7123889, -3.14159, -1.5708,
1.5708, 3.14159, 4.7123889, 6.28318
},
xticklabels={
$-2\pi$, $-\frac{3\pi}{2}$, $-\pi$, $-\frac{\pi}{2}$,
$\frac{\pi}{2}$, $\pi$, $\frac{3\pi}{2}$, $2\pi$
}
]
\addplot [mark=none, ultra thick, blue] {sin(deg(x))};
\end{axis}
\end{tikzpicture}
\begin{tikzpicture}
\begin{axis}[
Axis Style,
xtick={
-6.28318, -4.7123889, -3.14159, -1.5708,
1.5708, 3.14159, 4.7123889, 6.28318
},
xticklabels={
$-2\pi$, $-\frac{3\pi}{2}$, $-\pi\hspace{0.30cm}$, $-\frac{\pi}{2}$,
$\frac{\pi}{2}$, $\pi\hspace{0.10cm}$, $\frac{3\pi}{2}$, $\hspace{0.25cm} 2\pi$
}
]
\addplot [mark=none, ultra thick, red] {sin(deg(x))};
\end{axis}
\end{tikzpicture}
\begin{tikzpicture}
\begin{axis}[
Axis Style,
xtick={-6.28318, -4.7123889, ..., 6.28318},
scaled x ticks={real:3.1415},
xtick scale label code/.code={},
xlabel={$x \thinspace [\times \pi]$}
]
\addplot [mark=none, ultra thick, brown] {sin(deg(x))};
\end{axis}
\end{tikzpicture}
\begin{tikzpicture}
\begin{axis}[
Axis Style,
xtick={-6.28318, -4.7123889, ..., 6.28318},
scaled x ticks={real:3.1415},
xtick scale label code/.code={$[\times \pi]$},
xlabel={$x$}
]
\addplot [mark=none, ultra thick, cyan] {sin(deg(x))};
\end{axis}
\end{tikzpicture}
\end{document}
-
+1 Is there a way to specify
xtick
using a\foreach
loop? This would be useful if one wanted to have different fractions of\pi
.– cmhughesNov 15, 2011 at 20:14 -
@cmhughes: I had attempted something similar and manually add the tick labels but have not come up with an elegant solution. See my related posts: Using macro defined lists in tikz pgfplot, and PGFplots foreach equivalent to TikZ's with multiple variables separated by a slash. Nov 15, 2011 at 20:23
-
@cmhughes: Also related: Macro to access a specific member of a list Nov 15, 2011 at 20:25
-
@cmhughes: See alternate solution which does not require you to specify each point explicitly. Nov 16, 2011 at 1:47
There is also a bit more "automated" solution which I first presented here (-- this seems to be a duplicate of this question --) with some more refinement inspired by this answer.
Please have a look at the comments of the code to find out, how it works.
% used PGFPlots v1.16
\documentclass[border=5pt]{standalone}
\usepackage{pgfplots}
\pgfplotsset{
axis lines=middle,
xlabel=$x$,
ylabel=$y$,
no markers,
samples=51,
trig format plots=rad,
%
% create a style to scale x axis values by \pi and
% remove the corresponding label
x axis in pi/.style={
scaled x ticks={real:\PI},
xtick scale label code/.code={},
% in case you want to set an explicit tick distance
xtick distance=pi/#1,
% add code here for formatting the `xticklabels'
% I configured exceptions for \pm\pi where no number in front
% of these are shown and for fractional values these should be
% shown as fractions
xticklabel={%
% to avoid some mess with TeX precision, first
% round the `\tick' value to one digit after the comma
\pgfmathparse{round(100*\tick)/100}
\ifdim \pgfmathresult pt = 1pt
\strut$\pi$%
\else\ifdim \pgfmathresult pt = -1pt
\strut$-\pi$%
\else
% depending on whether the resulting number is an integer
% show it as integer only, otherwise use the style given
% in `xticklabel style'
\pgfmathifisint{\pgfmathresult}{%
\strut$\pgfmathprintnumber[int detect]{\pgfmathresult}\pi$%
}{%
% show \pi next to the frac
\strut$\pgfmathprintnumber{\pgfmathresult}\pi$%
% % show \pi in the numerator of the frac
% \pgfmathparse{\pgfmathresult*#1}%
% \strut$\frac{\pgfmathprintnumber[int detect]{\pgfmathresult}\pi}{#1}$%
}
\fi\fi
},
% set number plotting to frac style
xticklabel style={
/pgf/number format/.cd,
frac,
frac whole=false,
% % if you prefer to have the same denominator value everywhere
% frac denom=#1,
},
},
}
% define precision of \pi
% this is set here to the value of \pgfmathpi
\pgfmathsetmacro{\PI}{pi}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
% % uncomment the next two lines for `x axis in pi=4' so the
% % `xticklabels' don't overlap
% width=1.5*\axisdefaultwidth,
% height=\axisdefaultheight,
domain=-1.1*pi:2.1*pi,
ymin=-1.1,
ymax=+1.1,
% apply the above created style
% (works for the values 1, 2 and 4)
x axis in pi=2,
ytick distance=1,
smooth,
]
\addplot {sin(x)};
\end{axis}
\end{tikzpicture}
\end{document}
-
-
Is it also possible to have $\frac{\pi}{2}$ instead of $\frac{1}{2}\pi$ etc.?– JuliaApr 25, 2017 at 19:12
-
If I change $\PI/2$ to $\PI/4$ in your code it doesn't work anymore (gives large fractions), changing 10 to 1000 in round, and loading fp solves this, but I didn't manage to make $\PI/8$ work...– JuliaApr 25, 2017 at 19:15
-
@Julia, of course you can encapsulate it into a style and you also can place
\pi
in the numerator of\frac
. Therefore see my edited code. Unfortunately I am also unable to make my solution work for\pi/8
, sorry. Apr 27, 2017 at 1:48
Here is another solution inspired by Stefan Pinnow's answer. To avoid the precision issue with /pgf/number format/frac
, it calculates explicitly the reduced fraction for every label, so it should work for pi/8, etc.
\documentclass[border=5pt]{standalone}
% Workaround for gcd() issue in pgfplots 1.14
% (see https://sourceforge.net/p/pgfplots/bugs/129/ and
% https://tex.stackexchange.com/questions/328972/ )
\usepackage{tikz}
\makeatletter
\let\pgfmathgcdX=\pgfmathgcd@
\usepackage{pgfplots}%
\let\pgfmathgcd@=\pgfmathgcdX
\makeatother
% Load math library, for \tikzmath
\usetikzlibrary{math}
\pgfplotsset{
% Typeset fractions of pi at regular intervals on x axis
x axis in pi/.style={
% Make sure the x axis is in radians
trig format plots=rad,
% Set tick distance from style argument
xtick distance={pi/#1},
% Set label style: calculate reduced fraction of pi
xticklabel={
\tikzmath{
% Calculate this tick's multiple of pi/#1
int \numorig, \gcd, \num, \denom, \absnum;
\numorig = round(\tick*#1/pi);
% Calculate reduced fraction for \numorig/#1
\gcd = gcd(\numorig,#1);
\num = \numorig / \gcd;
\absnum = abs(\num);
\denom = #1 / \gcd;
% Build label text
if \num < 0 then {
let \sign = -;
} else {
let \sign =;
};
if \absnum == 1 then {
let \numpi = \pi;
} else {
let \numpi = \absnum\pi;
};
if \denom == 1 then {
if \num == 0 then {
{ \strut$0$ };
} else {
{ \strut$\sign\numpi$ };
};
} else {
{ \strut$\sign\frac{\numpi}{\denom}$ };
% Other style with all pi symbols same and aligned:
%{ \strut$\sign\frac{\absnum}{\denom}\pi$ };
};
}
},
},
}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
width=14cm,
axis equal image,
domain=-2*pi:2*pi,
axis lines=center,
enlargelimits={abs=0.4},
no markers,
samples=100,
ytick distance = 1,
x axis in pi=2, % tick distance as fraction of pi
]
\addplot {sin(x)};
\end{axis}
\end{tikzpicture}
\end{document}
-
The workaround for
gcd()
issue isn't needed anymore (at least inpgfplots
1.18). Jun 14 at 14:59 -
1Note that this code currently (
pgfplots
1.18) doesn't work with the beamer class. See tex.stackexchange.com/q/688609/18401. Jun 14 at 16:06
I realize the question is on PGFPlots, but I was interested in finding or providing in this case a solution using only TikZ code. Although the PGFPlots automation and mathematical nature of the code is appealing, I wonder if all the overhead is necessary for most Trig graphs. In any case, here is my solution. The one concern I had in making this graph was for the axes to represent true relative distances. Therefore, the x-axis is scaled by pi/4 while the y-axis is simply units of natural numbers.
\documentclass[border=5pt]{standalone}
\usepackage{amsmath} \usepackage{amsfonts} \usepackage{amssymb}
\usepackage{amsthm} \usepackage{latexsym} \usepackage{mathtools}
\usepackage{tikz}
\usetikzlibrary{arrows,automata,calc}
\begin{document}
\newcommand*{\xMin}{-9}
\newcommand*{\xMax}{9}
\newcommand*{\yMin}{-3}
\newcommand*{\yMax}{3}
\scriptsize
\begin{tikzpicture}[->,>=stealth,scale=0.65]
\foreach \i in {\xMin,...,\xMax} {
\draw [-,very thin,gray,scale={pi/4}] (\i,{-3/(pi/4)}) -- (\i,{3/(pi/4)});
}
\foreach \i in {\yMin,...,\yMax} {
\draw [-,very thin,gray] ({\xMin*pi/4},\i) -- ({\xMax*pi/4},\i);
}
\draw node at ({pi},0) [below] {${\pi}$};
\draw node at ({2*pi},0) [below] [xshift=1pt] {${2\pi}$};
\draw node at ({-pi},0) [below] [xshift=-2pt] {${-\pi}$};
\draw node at ({-2*pi},0) [below] [xshift=-2pt] {${-2\pi}$};
\draw node at (0,1) [left] {$1$};
\draw node at (0,2) [left] {$2$};
\draw node at (0,-1) [left] {$-1$};
\draw node at (0,-2) [left] {$-2$};
\draw [->] [thick] ({\xMin*(pi/4)},0) -- ({\xMax*(pi/4)+0.5},0)
node [right] {$x$};
\draw [->] [thick] (0,-3) -- (0,3.5)
node [pos=0.45] [xshift=-3.5pt,yshift=-2pt] {$o$}
node [above] {$y$};
\draw [-,thick,magenta,domain={-2*pi}:{2*pi},samples=100]
plot (\x, {sin(\x*180/pi)});
\end{tikzpicture}
\normalsize
\end{document}
pgfplots
manual pages 262-263 (manual for version 1.5, of July 29 2011) for a solution. (Assuming you're after the labels on thex
-axis.)\documentclass
and the appropriate packages so that those trying to help don't have to recreate it.