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

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}
\usepackage{pgfplotstable} % For \pgfplotstableread

\pgfplotstableread{
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]
\addplot table  {\datatable}
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}

sample code output

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
    ]
        \addplot+[domain=-3:4,mark=none,forget plot] {f(x)};
        \addplot+[samples at={-1.8117,-1,0,0.5,2,3.3117},only marks] {f(x)}
            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}

second sample code output

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}
\usepackage{pgfplotstable} % For \pgfplotstableread
\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
    }
}

\pgfplotstableread{
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]
\addplot +[
    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}
\usepackage{pgfplotstable} % For \pgfplotstableread

\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
    }
}

\pgfplotstableread{
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]
\addplot +[
    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}
\usepackage{pgfplotstable} % For \pgfplotstableread

\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
    }
}

\pgfplotstableread{
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]
\addplot +[
    pins near some coords={1/south:Bragg valley,3/Bragg peak}
] table {\datatable};

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