pgfplots を使用しているときに、foreach 変数を addplot のパラメーターとして使用しようとすると、「未定義の制御シーケンス」が発生するのはなぜですか?

pgfplots を使用しているときに、foreach 変数を addplot のパラメーターとして使用しようとすると、「未定義の制御シーケンス」が発生するのはなぜですか?

エラー バー付きのプロットが複数あるため、エラー バーを少しずらしてプロット全体をより読みやすくしたいと思います。ただし、\foreachシフト量として変数 a を使用してこれを実行しようとすると、「未定義の制御シーケンス」エラーが発生します。

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

(2 つのコメントのいずれかをコメント解除すると、ドキュメントはコンパイルされません。)

ここで何が問題なのですか?

編集: に別の変数を追加しました\foreach。実際の使用例では、データをプロットするファイル名や曲線に使用するラベルが含まれます。

答え1

問題はマクロの展開の問題です。\y変数は後で評価されますが、その「後で」の時点ではループは終了しており、\y未定義です。

すでに述べたように、\pgfplotsinvokeforeachにはループ引数が 1 つだけあります ( は\pgfplotsforeachungrouped2 つの引数をサポートしていますが、ここでは役に立ちません)。

ここで、いつもループがどんなに複雑であっても、次のように動作します。

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

\edefループ本体全体をカバーする人工的な を導入しました。これは\edef「拡張定義」を意味します。つまり、 は\temp中括弧内のすべてのものの完全に拡張された結果であると定義されます。これは\y現在のループ値に拡張されます。残念ながら、これも拡張しようとしますが、これは不可能です。この拡張を回避するために、の前に\addplotTeX プリミティブを記述しました。\noexpand\addplot

最後に\tempループ本体が含まれますそれなし\yまたはへの参照はありません。ループ本体に\x書き込むだけで実行できます。これで目的は達成されます。\temp


興味深いことに、座標リストを の外側に残すこともできます\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}

これは、TeX が拡張によって動作するため、実際に機能します。つまり、「実行」するとすぐに\temp、それが「内部」にあるという事実については何も認識せず\temp、単に先読みするだけになります。

見るhttp://pgfplots.sourceforge.net/TeX-プログラミングノート.pdf詳細については

関連情報