我有一些想要读取和绘制的表格,每个表格都有自己的风格。为了方便起见,我喜欢使用相同的标签。以下是 MWE:
\documentclass{minimal}
\usepackage{pgfplotstable}
\begin{filecontents}{tabA.dat}
x y
0 0
1 1
2 2
3 3
\end{filecontents}
\begin{filecontents}{tabB.dat}
x y
0 1
1 2
2 3
3 4
\end{filecontents}
\pgfplotsset{compat=newest,
tabA/.style={color=red,mark=*},
tabB/.style={color=black,mark=o},
}
\pgfplotstableread{tabA.dat}\tabA
\pgfplotstableread{tabB.dat}\tabB
\begin{document}
\begin{tikzpicture}
\begin{axis}[legend,legend pos=south east]
\addplot[tabA] table[x=x,y=y] {\tabA};\label{pgf:tabA}\addlegendentry{tabA}
\addplot[tabB] table[x=x,y=y] {\tabB};\label{pgf:tabB}\addlegendentry{tabB}
\end{axis}
\end{tikzpicture}
\end{document}
\pgfplotsforeachinvoke
我可以使用或实现相同的结果吗\foreach
?例如
\begin{tikzpicture}
\begin{axis}[legend,legend pos=south east]
\pgfplotsinvokeforeach{tabA,tabB}{%
% The following doesn't work, of course
\addplot[#1] table[x=x,y=y] {\#1}; % <- Magic goes here
}
\end{axis}
\end{tikzpicture}
当然,在这个简单的例子中,我可以简单地使用
\addplot[#1] table[x=x,y=y] {#1.dat};
但有时文件的名称不符合某种模式,或者有时我只想读取和存储一个表以便修改它或多次重复使用它。
答案1
欢迎来到 TeX.SE!有一件事总是有可能的:
编写一个宏,按照您想要的方式组装一个标记列表(这里,将一系列
\addplot
命令与适当的选项连接起来);然后使用第二个宏(在我的代码中,由的第二个参数构造
\foreachTable
),输出类似的内容\begin{axis}[...]#1\end{axis}
,并#1
用包含所有命令的先前组装的标记列表替换\addplot
。
这种技术总是有效(一旦第二个宏被展开,TeX 输入流就和你手动输入所有代码的状态完全相同)。因此,你可以使用它以编程方式生成表格、图片,以及任何你想要的东西。
完整代码:
\begin{filecontents}{tabA.dat}
x y
0 0
1 1
2 2
3 3
\end{filecontents}
\begin{filecontents}{tabB.dat}
x y
0 1
1 2
2 3
3 4
\end{filecontents}
\documentclass[tikz, border=2mm]{standalone}
\usepackage{xparse}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}
\ExplSyntaxOn
\seq_new:N \l__millo_plot_cmds_tl
\cs_new_protected:Npn \millo_foreach_table_do_axis:nNn #1#2#3
{
\tl_clear:N \l__millo_plot_cmds_tl
\clist_map_inline:nn {#1}
{
\tl_set:Nn \l_tmpa_tl {#3}
\regex_replace_all:nnN { \c{myTable} } { \c{##1} } \l_tmpa_tl
\tl_put_right:NV \l__millo_plot_cmds_tl \l_tmpa_tl
}
\exp_args:No #2 \l__millo_plot_cmds_tl
}
\NewDocumentCommand \foreachTable { m m m }
{
\cs_set_protected:Npn \__millo_axis_func:n ##1 {#2}
\millo_foreach_table_do_axis:nNn {#1} \__millo_axis_func:n {#3}
}
\ExplSyntaxOff
\pgfplotsset{
tabA/.style={color=red,mark=*},
tabB/.style={color=black,mark=o},
}
\pgfplotstableread{tabA.dat}\tabA
\pgfplotstableread{tabB.dat}\tabB
\begin{document}
\begin{tikzpicture}
\foreachTable{tabA, tabB}
{
\begin{axis}[legend, legend pos=south east]
#1
\end{axis}
}
{ \addplot[#1] table[x=x,y=y] {\myTable}; \addlegendentry{#1} }
\end{tikzpicture}
\end{document}
调用说明:
\foreachTable{tabA, tabB}
{
\begin{axis}[legend, legend pos=south east]
#1
\end{axis}
}
{ \addplot[#1] table[x=x,y=y] {\myTable}; \addlegendentry{#1} }
第一个参数是条目列表(每个条目指向一个\addplot
命令)。
#1
第二个参数是内部内容被自动生成的命令替换后将插入的内容\addplot
。
第三个参数指定每个自动生成的图的代码,并进行一些方便的替换:
#1
替换为条目名称(此处:tabA
thentabB
);\myTable
用由条目名称构建的控制序列标记替换(此处:\tabA
对于第一个条目,\tabB
对于第二个条目)。
如果您想手动添加更多图(此处,一个在自动生成的图之前,一个在自动生成的图之后),您可以例如执行以下操作:
\foreachTable{tabA, tabB}
{
\begin{axis}[legend, legend pos=south east]
\addplot {sin(deg(\x))}; \addlegendentry{$\sin$}
#1
\addplot {sqrt(\x)}; \addlegendentry{$x\mapsto \sqrt{x}$}
\end{axis}
}
{ \addplot[#1] table[x=x,y=y] {\myTable}; \addlegendentry{#1} }
对于没有\regex_replace_all:nnN
如果您的l3kernel
年龄太大,无法拥有\regex_replace_all:nnN
,您可以:
\cs_generate_variant:Nn \tl_replace_all:Nnn { Nno }
在 之前添加\cs_new_protected:Npn \millo_foreach_table_do_axis:nNn #1#2#3
;更换线路
\regex_replace_all:nnN { \c{myTable} } { \c{##1} } \l_tmpa_tl
和
\exp_args:NNno \tl_replace_all:Nno \l_tmpa_tl { \myTable } { \use:c {##1} }
那么它应该可以工作在条件下不在\myTable
括号内使用。例如,使用
\foreachTable{tabA, tabB}
{
...
}
{ \addplot[#1] table[x=x,y=y] \myTable; \addlegendentry{#1} }
代替:
\foreachTable{tabA, tabB}
{
...
}
{ \addplot[#1] table[x=x,y=y] {\myTable}; \addlegendentry{#1} }