由于我有多个带有误差线的图,我想稍微移动误差线以使整个图更具可读性。但是,当我尝试使用变量 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了解详情