Проблемы с генерацией матрицы tikz (или табличной) с использованием \pgfplotstableforeachcolumn

Проблемы с генерацией матрицы tikz (или табличной) с использованием \pgfplotstableforeachcolumn

Я пытаюсь создать 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то же самое, что и , за {исключением того, что его можно добавить в некоторый «строкостроитель», хотя связанный объект }отсутствует (т.е. \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. Но это выходит за рамки моего ответа.

Связанный контент