![Al utilizar pgfplots, ¿por qué obtengo una "secuencia de control indefinida" cuando intento utilizar una variable foreach como parámetro para addplot?](https://rvso.com/image/254718/Al%20utilizar%20pgfplots%2C%20%C2%BFpor%20qu%C3%A9%20obtengo%20una%20%22secuencia%20de%20control%20indefinida%22%20cuando%20intento%20utilizar%20una%20variable%20foreach%20como%20par%C3%A1metro%20para%20addplot%3F.png)
Como tengo varios gráficos con barras de error, me gustaría cambiar ligeramente las barras de error para que el gráfico general sea más legible. Sin embargo, cuando intento hacer esto usando la variable a \foreach
como cantidad a desplazar, aparece un error de "secuencia de control indefinida".
\documentclass{article}
\usepackage{tikz}
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture}
\begin{axis}
\foreach \x/\y in {a/-1cm, b/0cm, c/1cm} {
\addplot+ [
%every error bar/.append style={xshift=\y},
%every node/.style={xshift=\y},
error bars/y dir=both,
error bars/y explicit,
] coordinates {
(0, 0) +- (0, 1)
(1, 0) +- (0, 1)
(2, 0) +- (0, 1)
};
}
\end{axis}
\end{tikzpicture}
\end{document}
(El documento no se compila cuando descomento cualquiera de los dos comentarios).
¿Qué pasa aquí?
EDITAR: Se agregó otra variable al archivo \foreach
. En mi caso de uso real, contendría el nombre del archivo para trazar los datos o la etiqueta que se usará para la curva.
Respuesta1
El problema es una cuestión de expansión macro: la \y
variable se evalúa más tarde, pero en ese momento "posterior", el ciclo ha finalizado y \y
no está definido.
Como ya se mencionó, \pgfplotsinvokeforeach
tiene solo un argumento de bucle (tenga en cuenta que \pgfplotsforeachungrouped
admite dos argumentos, pero no ayuda aquí).
He aquí un enfoque quesiemprefunciona, no importa cuán complicados sean tus bucles:
\begin{tikzpicture}
\begin{axis}
\foreach \x/\y in {a/-1cm, b/0cm, c/1cm} {
\edef\temp{
\noexpand\addplot+ [
every error bar/.append style={xshift=\y},
every node/.style={xshift=\y},
error bars/y dir=both,
error bars/y explicit,
]
coordinates {
(0, 0) +- (0, 1)
(1, 0) +- (0, 1)
(2, 0) +- (0, 1)
};
}
\temp
}
\end{axis}
\end{tikzpicture}
Introduje un artificial \edef
que cubre todo el cuerpo del bucle. Esto \edef
significa "definición ampliada": define \temp
como el resultado completamente expandido de todo lo que está dentro de las llaves. Esto se expandirá \y
al valor del bucle actual. Desafortunadamente, también (intentará) expandirse \addplot
, lo cual es imposible. Para evitar esta expansión, escribí la primitiva TeX \noexpand
delante de \addplot
.
Finalmente, \temp
contiene el cuerpo del bucle.sincualquier referencia a \y
o \x
. Simplemente podemos ejecutarlo escribiendo \temp
en el cuerpo del bucle. Eso hace el trabajo.
Sólo para los curiosos: puedes dejar la lista de coordenadas fuera de \edef
:
\begin{tikzpicture}
\begin{axis}
\foreach \x/\y in {a/-1cm, b/0cm, c/1cm} {
\edef\temp{
\noexpand\addplot+ [
every error bar/.append style={xshift=\y},
every node/.style={xshift=\y},
error bars/y dir=both,
error bars/y explicit,
]
}
\temp
coordinates {
(0, 0) +- (0, 1)
(1, 0) +- (0, 1)
(2, 0) +- (0, 1)
};
}
\end{axis}
\end{tikzpicture}
Esto también funciona porque TeX funciona mediante expansión: tan pronto como se "ejecuta" \temp
, ya no sabe nada sobre el hecho de que está "dentro" \temp
y simplemente seguirá leyendo.
Verhttp://pgfplots.sourceforge.net/TeX-programming-notes.pdfpara detalles