# How to mark/label nth data point from file in pgfplots?

\documentclass{standalone}

\usepackage{pgfplots}
\usepackage{pgfplotstable}
\pgfplotsset{compat=1.10}

0.01    1.00
0.02    2.00
0.03    3.00
0.04    4.00
0.05    5.00
}\datatable

\begin{document}
\begin{tikzpicture}
\begin{axis}[ymin=0, ymax=6]
node[pos=0.0, pin=above:"Unidentified peak"]{} % pos only allows for fractional value
node[pos=0.2, pin=above:"Bragg peak"]{} % pos only allows for fractional value
node[pos=1.0, pin=above:"my custom label"]{} % pos only allows for fractional value
;

\end{axis}
\end{tikzpicture}
\end{document}


UPDATE: A slightly shorter version of the second solution in the answer by @Matthew Leingang:

\documentclass{standalone}

\usepackage{pgfplots}
\pgfplotsset{compat=1.10}

0.01    1.00
0.011   2.00
0.012   3.00
0.013    4.00
0.05    5.00
}\datatable

\pgfplotstablegetrowsof{\datatable}
\pgfmathsetmacro{\N}{\pgfplotsretval}

\begin{document}
\begin{tikzpicture}
\begin{axis}[ymin=0, ymax=6]
% pos = (index-1)/(N-1)  (index starting from 1)
node[pos=(1-1)/(\N-1), pin=right:first point (1/\N)]{}
node[pos=(3-1)/(\N-1), pin=-45:third point (3/\N)]{}
node[pos=(4-1)/(\N-1), pin=-45:end of linear behaviour (4/\N)]{}
;
\end{axis}
\end{tikzpicture}
\end{document}


• Do you want to label just the nth point, or every nth point? For example, do you want to label just point number 2, or also points 4, 6, 8...? – Jake Jul 14 '14 at 10:17
• just the nth point, possibly an arbitrary number of points, specified by their line number / index, e.g. (1, 2, 5). – Hotschke Jul 14 '14 at 10:17

I think the easiest way to do it is as you've done, keeping in mind that if there are N equally spaced points, the pos-ition of the n-th point is (n-1)/(N-1).

In your case you have 5 points and you want to mark the second, so it should be at position 0.25:

\documentclass{standalone}

\usepackage{pgfplots}

0.01    1.00
0.02    2.00
0.03    3.00
0.04    4.00
0.05    5.00
}\datatable

\begin{document}
\begin{tikzpicture}
\begin{axis}[ymin=0, ymax=6]
node[pos=0.0, pin=right:first point'']{}
node[pos=0.25, pin=above:second point'']{}
node[pos=1.0, pin=left:last point'']{}
;

\end{axis}
\end{tikzpicture}
\end{document}


This will work as along as your points are evenly spaced. If they are not, you have two choices that I know of:

1. calculate the relative position based on the point coordinates. If they are labeled x_1, x_2, ..., x_N, the n-th point is at position (x_n - x_1)/(x_N - x_1).

2. Use a plot handler that only plots the points without interpolation, e.g., only marks. Then you can use fractional positions and the handler will “snap to” the point indexed by that fraction. So if there are five points pos=0.25 will snap to the second point regardless of whether it is really 1/4th of the way from the left to right.

If you have unevenly spaced points and you want to mark them, interpolate them, and label them, you can use a two-step approach. First, plot without marks with \addplot+[mark=none,forget plot] ... Then plot only marks and label with \addplot+[only marks] ... node[pos=0.25] .... Here is an example of that:

\documentclass{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.8}
\begin{document}

\begin{tikzpicture}[
declare function={
f(\x) = 2*(\x)^3 - 3*(\x)^2 - 12 *\x;
}]
\begin{axis}[
width=\linewidth,
xmin=-3.3,xmax=4,
ymin=-21,ymax=21,
xtick={-1,0.5,2},
xticklabels={$-1$,$\frac12$,$2$},
ytick=\empty,
samples=50
]
node[pos=0,
pin={-88:$\left(\frac{1}{4}\left(3 - \sqrt{105}\right),0\right)$},
] {}
node[pos=0.2,pin={$(-1,7)$}] {}
node[pos=0.4,pin={15:$(0,0)$}] {}
node[pos=0.6,pin={0:$\left(\frac12,-6\frac12\right)$}] {}
node[pos=0.8,pin={90:$(2,-20)$}] {}
node[pos=1.0,pin={95:$\left(\frac{1}{4}\left(3 + \sqrt{105}\right),0\right)$}] {}
;
\end{axis}
\end{tikzpicture}
\end{document}


The forget plot command keeps the plot cycle from shifting so the second plot is styled exactly as the first one is. The second \addplot marks specific (unevenly spaced) points. Since there are six of them, the position of the n-th is 0.2n.

I would use the nodes near coords functionality for this, which allows you to associate the labels directly with the coordinates, regardless of the spacing. With a bit of TikZ style acrobatics, you can define a key

nodes near some coords={1,3}


that takes either a single coordinate index or a list of indices, and activates the label printing only for those coordinates:

\documentclass{standalone}

\usepackage{pgfplots}
\pgfplotsset{compat=1.10}

\pgfplotsset{
node near coord/.style={ % Style for activating the label for a single coordinate
nodes near coords*={
\ifnum\coordindex=#1\pgfmathprintnumber{\pgfplotspointmeta}\fi
}
},
nodes near some coords/.style={ % Style for activating the label for a list of coordinates
scatter/@pre marker code/.code={},% Reset the default scatter style, so we don't get coloured markers
scatter/@post marker code/.code={},%
node near coord/.list={#1} % Run "node near coord" once for every element in the list
}
}

0.01    1.00
0.02    2.00
0.024    3.00
0.04    4.00
0.05    5.00
}\datatable

\begin{document}
\begin{tikzpicture}
\begin{axis}[ymin=0, ymax=6, every node near coord/.style=above left]
nodes near some coords=0
] table {\datatable};

\end{axis}
\end{tikzpicture}
\end{document}


The same approach can also be used to supply the label to be printed for each coordinate, and the desired alignment.

Calling

\addplot +[
nodes near some coords={1/Bragg valley/below,3/Bragg peak/above}
] table {\datatable};


will yield the following:

\documentclass{standalone}

\usepackage{pgfplots}

\pgfplotsset{
node near coord/.style args={#1/#2/#3}{% Style for activating the label for a single coordinate
nodes near coords*={
\ifnum\coordindex=#1 #2\fi
},
scatter/@pre marker code/.append code={
\ifnum\coordindex=#1 \pgfplotsset{every node near coord/.append style=#3}\fi
}
},
nodes near some coords/.style={ % Style for activating the label for a list of coordinates
scatter/@pre marker code/.code={},% Reset the default scatter style, so we don't get coloured markers
scatter/@post marker code/.code={},%
node near coord/.list={#1} % Run "node near coord" once for every element in the list
}
}

0.01    3.00
0.02    2.00
0.024    3.00
0.04    4.00
0.05    1.00
}\datatable

\begin{document}
\begin{tikzpicture}
\begin{axis}[ymin=0, ymax=6, every node near coord/.style=above left]
nodes near some coords={1/Bragg valley/below,3/Bragg peak/above}
] table {\datatable};

\end{axis}
\end{tikzpicture}
\end{document}


If you want to use pins, you can use a slightly altered (and slightly more elegant) version of the approach:

\documentclass{standalone}

\usepackage{pgfplots}

\pgfplotsset{
pin near coord/.style args={#1/#2}{% Style for activating the label for a single coordinate
scatter/@pre marker code/.append code={
\ifnum\coordindex=#1 \node[pin=#2]{};\fi
}
},
pins near some coords/.style={ % Style for activating the label for a list of coordinates
scatter,
scatter/@pre marker code/.code={},% Reset the default scatter style, so we don't get coloured markers
scatter/@post marker code/.code={},%
pin near coord/.list={#1} % Run "pin near coord" once for every element in the list
}
}

0.01    3.00
0.02    2.00
0.024    3.00
0.04    4.00
0.05    1.00
}\datatable

\begin{document}
\begin{tikzpicture}
\begin{axis}[ymin=0, ymax=6, every node near coord/.style=above left]

• node near coord is something I should learn more about. Would there be a way to specify the point meta in the table and display it automagically? – Matthew Leingang Jul 14 '14 at 19:13
• I'd like to use a custom label text, not the index or the value. Is this also possible with node near coord? – Hotschke Jul 15 '14 at 8:08
• @MatthewLeingang: Yes, that's possible. You can add a column to the table that contains the meta value or text, and then use \addplot table [meta index=<column number>] ..., for instance. – Jake Jul 15 '14 at 8:17
• @Hotschke: Quite obviously the more compact "user side" code. The "setup" is limited to the one \pgfplotsset block. – Jake Jul 15 '14 at 10:17