1

I'm trying to generate a tikz picture from data in a table file, reading it through pgfplotstable (and I'm not plotting the data directly, so I cannot use pgfplots directly).

The first step is to be able to iterate through the elements of the table to generate a tikz matrix, but I have problems that I cannot explain.

Here is a minimal example:

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

which gives cryptic error messages like:

./mwe.tex:21: Undefined control sequence. [ }]
./mwe.tex:21: Missing number, treated as zero. [ }]

Swapping the tikz matrix for a tabular yields the same errors. It seems the problem comes from the \\ command, because if I remove it, making it generate only one cell, the loop works. The same problem happens also trying to generate rows of a tabular instead of a tikz matrix. Note that using other iterating methods, like the \foreach macro, work inside the matrix (or tabular), but then I don't have any way to iterate over the tables columns.

What am I missing?

2

Unfortunately, any kind of TeX looping constructs inside of \begin{tabular} or other tabulated environments like \matrix do not work. This is a limitation of TeX which has its own understanding of what it sees and what it executes.

What you need to do is to write some code which generates something like the following snipped and then instructs TeX to process it without further executable instructions in-between:

\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 ;%

I chose the formulation above as it resembles what the output of my code generation shown below -- but any other code generator will have to result in the same (or similar) output. Note that

  • \bgroup is the same as { except that it can be appended into some "stringbuilder" although the associated } is missing (i.e. \bgroup is an unbalanced form of {)
  • \pgfmatrixnextcell is something that the PGF manual provides if \matrix code is generated in some macro. For some technical reason, the matrix code does not support & if that is the case (please refer to the PGF manual for details).

I wish it would be simpler, but TeX is far from simple (which is why you asked this question here, of course).

The package pgfplotstable is nothing but a sophisticated code-generator for CSV data. The following snippet customizes its output such that it generates a PGF matrix of nodes:

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

enter image description here

Note that I have taken the freedom to output the entire CSV input table, even though your attempt only considers parts of it. If my solution appears to be the right direction, you can find lots of keys to customize the column names, the selection of output columns, the output rows etc in pgfplotstable.

I suppose this is a relatively elegant solution, although - I bet - it leaves either you or some other visitor of this site wondering "how could I possibly do the same with a simple piece of code". The answer is: either by means of more control of the TeX macro language ("TeX expansion control", see Where do I start LaTeX programming?) or by means of LUA code which assembles the statements and spits out executable TeX code. But that is beyond my answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.