使用 pgfplots,為什麼在嘗試使用 foreach 變數作為 addplot 的參數時會收到「未定義的控制序列」?

使用 pgfplots,為什麼在嘗試使用 foreach 變數作為 addplot 的參數時會收到「未定義的控制序列」?

由於我有多個帶有誤差線的圖,因此我想稍微移動誤差線以使整體圖更具可讀性。但是,當我嘗試使用變數 a\foreach作為移位量來執行此操作時,我收到“未定義的控制序列”錯誤。

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

(當我取消註釋這兩個註釋之一時,該文件不會編譯。)

這是怎麼回事?

編輯: 新增了另一個變數到\foreach.在我的實際用例中,它將包含用於繪製資料的檔案名稱或用於曲線的標籤。

答案1

問題是巨集擴展問題:\y稍後評估變數 - 但在「稍後」時間,循環已完成且未\y定義。

正如已經提到的,\pgfplotsinvokeforeach只有一個循環參數(注意\pgfplotsforeachungrouped支援兩個參數,但在這裡沒有幫助)。

這是一種方法總是工作,無論你的循環有多複雜:

\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到當前循環值。不幸的是,它也會(嘗試)擴張\addplot——這是不可能的。為了避免這種擴展,我將 TeX 原語寫\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-programming-notes.pdf欲了解詳情

相關內容