PGFplots foreach equivalent to TikZ's with multiple variables separated by a slash

There is exactly one reason why there are pgfplots equivalents to the \foreach command of pgf/tikz: scoping. Occasionally, one wants to aggregrate things, i.e. to compute a value which exists outside of the loop's body -- but which is not global either.

If you do not care about scoping and if you are not aggregrating things, the use of \foreach might be the correct choice.

A solution to you approaches might be to tweak the expansion sequence, i.e. to replace the \x and \l macros by their respective value in a "correct way" (see below).

However, there is one particular thing which makes loops in pgfplots a little bit technical: the fact that an axis first just collects its content (evaluating things like axis limits and the-like) following by a visualization phase which actually draws things. Unfortunately, this leads to problems with expansions. What happens if \l is stored back - and is not actually being evaluated until finally \end{axis} starts the survey phase and tries to recover its meaning? Well - it fails because \l has only a well-defined meaning inside of the loop.

Pgfplots offers the \pgfplotsinvokeforeach thing for basic loops: it does not need expansion and directly inserts the value of the loop variable.

The most flexible way, however, is to tweak the expansion sequence -- it allows to use the full flexibility of TikZ's \foreach statement; and it is not so difficult.

It can be used as follows:


\foreach \x/\l in {-2/a, -1/b, 1/c, 2/d}{
   \edef\temp{\noexpand\addplot [mark=none,color=red, thin, samples=2]%
       coordinates{ (\x,-0.05) (\x,0.05) }
        node [red, below] {\l};
   }
   % \show\temp %-- uncomment this to see what the \temp macro does
   \temp
} 

What happens is that inside of the loop body, a temporary macro \temp is defined. The \edef is a TeX instruction (which is not usually used for LaTeX). It means "expanded definition". It defines \temp to be the fully expanded result of the argument in braces. The \noexpand means "insert the next following token literally rather than expanding it". It expands to \addplot (i.e. it simply keeps it). When using \edef, you need to prefix anything which shall be kept as-is with \noexpand. The occurances \x and \l are both replaced by their respective values. Finally, the call to \temp invokes the result -- and it is unaware of the enclosing loop.

Just a further detail: if you use the loop variable inside of coordinates {...} or inside of anything else which is needed to compute axis limits, it is directly expanded (since pgfplots needs to survey the data). Only visualization instructions like the node are postponed until \end{axis}.


A different approach to this expansion problem. Using \pgfplotsinvokeforeach and a key defined with .code args (which is basically just a macro with delimited arguments).

If you need the full power of \foreach you will either need to fake it inside the plot as explained in another example

Code

\documentclass[tikz]{standalone}
\usepackage{pgfplots}
\newcommand*{\ListWithLabels}{-2/a, -1/b, 1/c, 2/d}
\newcommand*\pgfplotsinvokeforeachmacro[1]
  {\expandafter\pgfplotsinvokeforeach\expandafter{#1}}
\begin{document}
\begin{tikzpicture}
\begin{axis}
\pgfplotsset{my plot/.code args={#1/#2}{%
  \addplot[mark=none, color=red, thick, samples=2] coordinates {(#1,-.08) (#1,.08)}
    node[red, below] {#2};}}
\pgfplotsinvokeforeachmacro\ListWithLabels{\pgfplotsset{my plot={#1}}}
\end{axis}
\end{tikzpicture}
\end{document}

Code with dependencies

\documentclass[tikz]{standalone}
\usepackage{pgfplots}
\newcommand*{\ListWithLabels}{-2/a, -1/b, 1/c, 2/d}
\newcommand*\pgfplotsinvokeforeachmacro[1]
  {\expandafter\pgfplotsinvokeforeach\expandafter{#1}}
\makeatletter
\pgfplotsset{my color/.code args={#1!#2!#3}{%
  \pgfmathsetmacro\pgfplots@tempa{#2}%
  \pgfkeysalso{color=#1!\pgfplots@tempa!#3}}}
\makeatother
\begin{document}
\begin{tikzpicture}
\begin{axis}
\pgfplotsset{my plot/.code args={#1/#2}{%
  \addplot[mark=none, my color=red!(#1+2)/4*100!green, thick, samples=2]
    coordinates {(#1,-.08) (#1,.08)} node[red, below] {#2};}}
\pgfplotsinvokeforeachmacro\ListWithLabels{\pgfplotsset{my plot={#1}}}
\end{axis}
\end{tikzpicture}
\end{document}