![使用 \csname 和 \addplot 迭代已加载的 pgfplots 表](https://linux22.com/image/436200/%E4%BD%BF%E7%94%A8%20%5Ccsname%20%E5%92%8C%20%5Caddplot%20%E8%BF%AD%E4%BB%A3%E5%B7%B2%E5%8A%A0%E8%BD%BD%E7%9A%84%20pgfplots%20%E8%A1%A8.png)
我正在尝试创建一个 pgfplots 组图,其中每条曲线都是以自动方式从预加载的 pgfplots 表生成的。预期应用是用于涉及许多表的复杂绘图。下面的 MWE 说明了这个问题。适当使用\expandafter
(感谢上一个问题的答案:通过 csname 引用已加载的 pgfplotstable),我可以对多个表进行循环以使用\pgfplotstabletypeset
。尝试绘制两个数据集的类似循环无法编译。我希望能够\addplot
在这样的循环中使用未改变的语法。可能有一种方法可以将调用包装\addplot
在中\newcommand
,这可以使\expandafter
技巧奏效,但为每个我想要绘制的图定义一个新宏会很不方便,而且可能很脆弱。理想情况下,我希望能够 (1) 使用传递给的名称以不同的选项多次\pgfplotsinvokeforeach
调用\addplot
,以及 (2) 如果可能,切换到使用数字列表(例如\pgfplotsinvokeforeach{0,...,5}
)来实现绘图循环。
\documentclass{standalone}
\usepackage{pgfplots}
\usetikzlibrary{pgfplots.groupplots}
\usepackage{pgfplotstable}
\begin{document}
\pgfplotstableread{
a b
1 4
2 5
3 6
}{\testTableOne}
\pgfplotstableread{
a b
1 2
2 3
3 4
}{\testTableTwo}
\pgfplotsinvokeforeach{One,Two}{%
\expandafter\pgfplotstabletypeset\expandafter{\csname testTable#1\endcsname}
}
\begin{tikzpicture}
\begin{groupplot}[group style = {group size = 1 by 2}]
\pgfplotsinvokeforeach{One,Two}{
\nextgroupplot
\addplot table[ x = a, y = b ]
% This fails to compile
{\csname testTable#1\endcsname};
% This works, but doesn't vary the plot
%{\testTableOne};
}
\end{groupplot}
\end{tikzpicture}
\end{document}
答案1
我认为最好改变语法,这样控制扩展就更容易了。
\documentclass{article}
\usepackage{pgfplots}
\usetikzlibrary{pgfplots.groupplots}
\usepackage{pgfplotstable}
\ExplSyntaxOn
\NewDocumentCommand{\addplotnamedtable}{oO{}m}{%
\IfNoValueTF{#1}
{% the call is like \addplot table[...}{...}
\use:e { \exp_not:n { \addplot table~[#2] } { \exp_not:c { #3 } } }
}
{% the call is like \addplot [...] table [...] {...}
\use:e { \exp_not:n { \addplot [#1]~table~[#2] } { \exp_not:c { #3 } } }
}
}
\ExplSyntaxOff
\begin{document}
\pgfplotstableread{
a b
1 4
2 5
3 6
}{\testTableOne}
\pgfplotstableread{
a b
1 2
2 3
3 4
}{\testTableTwo}
\pgfplotsinvokeforeach{One,Two}{%
\expandafter\pgfplotstabletypeset\expandafter{\csname testTable#1\endcsname}
}
\begin{tikzpicture}
\begin{groupplot}[group style = {group size = 1 by 2}]
\pgfplotsinvokeforeach{One,Two}{
\nextgroupplot
\addplotnamedtable [sharp plot, mark=*, mark options={fill=green}][x = a, y = b ] {testTable#1};
}
\end{groupplot}
\end{tikzpicture}
\end{document}
答案2
解决上述问题中的第 (1) 项但不能解决第 (2) 项的解决方案是创建一个特殊版本\pgfplotstablecopy
。此版本采用第一个参数,该参数命名加载的表宏而不带前导\
字符。需要注意的是,\thisrow{}
在传递给的选项中使用table
似乎不适用于复制的表(但适用于原始表)。
\documentclass{standalone}
\usepackage{pgfplots}
\usepgfplotslibrary{groupplots}
\usepackage{pgfplotstable}
\begin{document}
\pgfplotstableread{
a b
1 4
2 5
3 6
}{\testTableOne}
\pgfplotstableread{
a b
1 2
2 3
3 4
}{\testTableTwo}
% Define the \backslashchar macro to be a \ character with a normal catcode.
% See https://tex.stackexchange.com/a/7372/61460 for an explanation. We will
% use this character below to trick pgfplotstable into allowing us to copying
% from a loaded table without using a leading \ in the name.
\begingroup\lccode`!=`\\\lowercase{\endgroup\def\backslashchar{!}}
% Make a special version of the macro \pgfplotstablecopy. This version copies
% from a loaded table specified as the first argument without a leading \.
\makeatletter
\newcommand{\Specialpgfplotstablecopy}[2]{%
\edef#2{\expandafter\noexpand\csname #1\endcsname}%
\expandafter\let\expandafter\pgfplotstable@loc@TMPa%
\csname\backslashchar\string#1@@table@name\endcsname
\expandafter\let\csname\string#2@@table@name\endcsname=\pgfplotstable@loc@TMPa
\expandafter\edef\csname\string#2@@table@scanline\endcsname{\csname\backslashchar\string#1@@table@scanline\endcsname}%
\expandafter\pgfplotslistforeachungrouped\csname#1\endcsname\as\pgfplotstable@loc@TMPa{%
\def\pgfplotstable@loc@TMPb{%
\expandafter\let\csname\string#2@\pgfplotstable@loc@TMPa\endcsname}%
\expandafter\pgfplotstable@loc@TMPb\csname\backslashchar\string#1@\pgfplotstable@loc@TMPa\endcsname
}%
}
\makeatother
\begin{tikzpicture}
\begin{groupplot}[group style = {group size = 1 by 2}]
\pgfplotsinvokeforeach{One,Two}{
\nextgroupplot
\Specialpgfplotstablecopy{testTable#1}{\tempTable};
\addplot[sharp plot, mark=*, mark options={fill=green}]
table[ x = a, y = b ] {\tempTable};
% Breaks due to the \thisrow{} expression.
% It works for the original table.
%\addplot[sharp plot, mark=*, mark options={fill=green}]
% table[ x = a, y expr = \thisrow{b} ] {\tempTable};
}
\end{groupplot}
\end{tikzpicture}
\end{document}