我正在尝试tikz
从表格文件中的数据生成图片并读取它pgfplotstable
(并且我没有直接绘制数据,因此我不能pgfplots
直接使用)。
第一步是能够遍历表的元素来生成 tikz 矩阵,但我遇到了无法解释的问题。
这是一个简单的例子:
\documentclass{standalone}
\usepackage{tikz}
\usepackage{pgfplotstable}
\usepackage{filecontents}
\usetikzlibrary{matrix}
\begin{filecontents*}{file.table}
col1 col2 col3 col4 col5
a b c d e
\end{filecontents*}
\begin{document}
\pgfplotstableread{file.table}\mytable
\begin{tikzpicture}
\matrix (plots) [matrix of nodes] {
\pgfplotstableforeachcolumn\mytable\as\col{%
\col \\
}
};
\end{tikzpicture}
% This also doesn't work
% \begin{tabular}{c}
% \pgfplotstableforeachcolumn\mytable\as\col{%
% \col \\
% }
% \end{tabular}
\end{document}
它给出了如下神秘的错误信息:
./mwe.tex:21: Undefined control sequence. [ }]
./mwe.tex:21: Missing number, treated as zero. [ }]
将 tikz 矩阵换成表格会产生相同的错误。问题似乎来自命令\\
,因为如果我删除它,使其仅生成一个单元格,循环就会起作用。尝试生成表格而不是 tikz 矩阵的行时也会出现同样的问题。请注意,使用其他迭代方法(如宏)可以\foreach
在矩阵(或表格)内工作,但我无法对表格列进行迭代。
我错过了什么?
答案1
不幸的是,任何类型的 TeX 循环构造在\begin{tabular}
或其他制表环境中,例如\matrix
不工作。这是 TeX 的一个限制,它对于所见和所执行的内容有自己的理解。
您需要做的是编写一些代码,生成类似以下片段的内容,然后指示 TeX 处理它,而无需中间进一步的可执行指令:
\matrix (plots) [matrix of nodes] \bgroup %
col1\pgfmatrixnextcell col2\pgfmatrixnextcell col3\pgfmatrixnextcell col4\pgfmatrixnextcell col5\\%
a\pgfmatrixnextcell b\pgfmatrixnextcell c\pgfmatrixnextcell d\pgfmatrixnextcell e\\%
\egroup ;%
我选择上面的公式是因为它类似于下面显示的代码生成的输出——但任何其他代码生成器都必须产生相同(或类似)的输出。请注意
\bgroup
与 相同,{
只是它可以被附加到某些“stringbuilder”中,尽管}
缺少关联(即,\bgroup
是不平衡的形式{
)\pgfmatrixnextcell
如果代码是在某些宏中生成的,则 PGF 手册会提供此功能\matrix
。由于某些技术原因,矩阵代码不支持&
这种情况(有关详细信息,请参阅 PGF 手册)。
我希望它会更简单,但 TeX 远非简单(当然这就是你在这里问这个问题的原因)。
该包pgfplotstable
只不过是一个复杂的 CSV 数据代码生成器。以下代码片段自定义了其输出,以便生成一个 PGF 节点矩阵:
\documentclass{standalone}
\usepackage{tikz}
\usepackage{pgfplotstable}
\usepackage{filecontents}
\usetikzlibrary{matrix}
\begin{filecontents*}{file.table}
col1 col2 col3 col4 col5
a b c d e
\end{filecontents*}
\begin{document}
\pgfplotstableread{file.table}\mytable
\begin{tikzpicture}
\pgfplotstabletypeset[
string type,
skip coltypes=true,
debug,
%
typeset cell/.code={%
% this here is more-or-less the default implementation, but it
% substitutes '&' by '\pgfmatrixnextcell':
\ifnum\pgfplotstablecol=\pgfplotstablecols
\pgfkeyssetvalue{/pgfplots/table/@cell content}{#1\\}%
\else
\pgfkeyssetvalue{/pgfplots/table/@cell content}{#1\pgfmatrixnextcell}%
\fi
},
% '\bgroup' / '\egroup' = '{' / '}' except that it does not need to be balanced
begin table={\matrix (plots) [matrix of nodes] \bgroup},
end table={\egroup;},
]{\mytable}
\end{tikzpicture}
\end{document}
请注意,我已自由输出整个 CSV 输入表,即使您的尝试仅考虑了其中的一部分。如果我的解决方案看起来是正确的方向,您可以在中找到许多键来自定义列名称、输出列的选择、输出行等pgfplotstable
。
我认为这是一个相对优雅的解决方案,尽管 - 我敢打赌 - 它会让你或本网站的其他访问者疑惑“我怎么可能用一段简单的代码做同样的事情”。答案是:要么通过对 TeX 宏语言的更多控制(“TeX 扩展控制”,见我应该从哪里开始 LaTeX 编程?)或者通过 Lua 代码来汇编语句并输出可执行的 TeX 代码。但这超出了我的回答范围。