# \foreach not behaving in axis environment

Am hesitant to ask yet one more embarrassing question, but I can't seem to see the problem with the \foreach in the MWE. It should produce several horizontal lines but only produces the one with the yValue as specified in the \newcommand{\yValue}{0.3}:

## Code:

\documentclass{article}
\usepackage{pgfplots}

\newcommand{\yValue}{0.3}

\begin{document}
\begin{tikzpicture}
\begin{axis}
[
ymin=0,
ymax=1,
xmin=0,
xmax=1,
]

\foreach \yValue in {0.00,0.1,...,1.00} {
\draw [red] (axis cs:0,\yValue) -- (axis cs:1,\yValue);
}

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

• \draw [red] foreach \yValue in {0.00,0.1,...,1.00} {(axis cs:0,\yValue) -- (axis cs:1,\yValue)}; does what you want. Apr 10, 2014 at 4:01
• Take a look at page 910 and 911 of the manual; it looks like you can use \foreach (or foreach) inside of a path, but you can't put a path inside of \foreach. At least, I assume the latter is true, since it doesn't work. The manual doesn't explicitly say that. Apr 10, 2014 at 4:04
• @Adam: That would be a fine solution to post for the MWE given, but I actually have to do more than one thing in the \foreach so not sure it'll work for my specific case. Also, Page 909 shows an example of what I am trying to use. Apr 10, 2014 at 4:06
• Ah, the answer seems to be at pages 470 and 471 of the pgfplots documentation. Apr 10, 2014 at 4:27

According to pages 470-471 of the pgfplots documentation:

(Note: in pgfplots documentation v1.17, the page range has changed to 544-545.)

Keep in mind that inside of an axis environment, all loop constructions (including custom loops, \foreach and \pgfplotsforeachungrouped) need to be handled with care: loop arguments can only be used in places where they are immediately evaluated; but pgfplots postpones the evaluation of many macros. For example, to loop over something and to generate axis descriptions of the form \node at (axis cs:\i,0.5)...., the loop macro \i will be evaluated in \end{axis} – but at that time, the loop is over and its value is lost. The correct way to handle such an application is to expand the loop variable explicitly.

Thus, you need to do:

\documentclass{article}
\usepackage{pgfplots}

\begin{document}
\begin{tikzpicture}
\begin{axis}
[
ymin=0,
ymax=1,
xmin=0,
xmax=1,
]

\foreach \yValue in {0.00,0.1,...,1.00} {
\edef\temp{\noexpand\draw [red] (axis cs:0,\yValue) -- (axis cs:1,\yValue);}
\temp
}

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


## Edit

As @percusee points out in the comments, you can also use \pgfplotsinvokeforeach. This is different from \foreach because, according to page 471 of the documentation:

the \x would not be expanded whereas #1 is.

That is to say, it does exactly what is needed to handle the fact that pgfplots doesn't evaluate loop macros until \end{axis}.

Thus, you can also do:

\pgfplotsinvokeforeach{0.00,0.1,...,1.00}{
\draw [red] (axis cs:0,#1) -- (axis cs:1,#1);
}


Note that the syntax is slightly different. \pgfplotsinvokeforeach uses #1, just like a \newcommand would, instead of allowing you to name your own variable.

• Great. Thanks. Am surprised that I have not encountered this problem until today, at least I don't recall that I have -- just in case someone comes up an answer of mine that uses this :-). Apr 10, 2014 at 4:40
• \pgfplotsinvokeforeach does this for you automatically. Apr 10, 2014 at 6:12
• @percusse Thanks for the tip. I've updated my answer accordingly. Apr 10, 2014 at 16:03
• How can we use \pgfplotsinvokeforeach in a nested way? Aug 19, 2017 at 19:18
• @bkarpuz Unfortunately, you can't. From the pgfplots documentation: "you can't nest this command yet (since it does not introduce protection by scopes)". Aug 22, 2017 at 19:40

I ran into a similar problem and the answers above didn't work for me. However, I realized that you often want to use foreach inside an axis environment because you want to have access to the axis cs coordinate system. I came up with the following workaround which I show here for the original MWE:

\documentclass{article}
\usepackage{pgfplots}
\usetikzlibrary{calc}

\begin{document}
\begin{tikzpicture}
\begin{axis}[ymin=0, ymax=1, xmin=0, xmax=1]
\coordinate (O) at (axis cs:0,0);
\coordinate (X) at (axis cs:1,0);
\coordinate (Y) at (axis cs:0,1);
\end{axis}
\begin{scope}[x={($(X)-(O)$)}, y={($(Y)-(O)$)}, shift={(O)}]
\foreach \y in {0, 0.1, ..., 1} {
\draw[red] (0,\y) -- (1,\y);
}
\end{scope}
\end{tikzpicture}
\end{document}


The idea obviously is that you "recreate" the coordinate system in the scope after leaving the axis environment. This also works with 3D coordinates. (Note that in newer versions of pgfplots you don't need the axis cs: prefix anymore.)

• Not sure who robust this solution is. Probably some options to tikzpicture or axis environment will break this, bit does seem to work for the given MWE. Mar 14, 2019 at 18:47
• @PeterGrill I've actually used this trick for quite complicated situations - for example, I mixed 3D mesh plots with blocks inserted by a foreach loop - and it worked fine so far. Mar 14, 2019 at 21:37