0

I'm currently experimenting with the pgfplots and pgfplotstable packages. I noticed the possibility to create new columns (copying or transforming another column) when I was wondering if it was possible to use spreadsheet like formulas (meaning the value of each cell of the new column should be the value of the cell to its left (same row) + the value of the cell above (same column), and yes there has to be some initializing).

Does anyone know of such a feature? And if yes how to do this? (regardless if it is only pgfplotstable or even pgfplots)

atticus
  • 557

1 Answers1

4

This can be done with some limitations using pgfplotstable's \pgfplotstablecreatecol macro (also with create on use to lazily create the column data, but its contents would then be lost after returning from \pgfplotstabletypeset). According to the pgfplotstable documentation:

Currently, you can only access three values of one column at a time: the current row, the previous row and the next row. Access to arbitrary indices is not (yet) supported.

In the example below, I implemented the formula described in the question, initializing it with (arbitrary) value 100 in “row -1.” Since the initial table data is:

 x   y
 0   1
 5   6
10  11

the computed values are:

  • 1 + 100 = 101

  • 6 + 101 = 107

  • 11 + 107 = 118

In order to access previously-computed values in the column being dynamically created, I store them globally (here: only the most recently computed value, using \xdef\myPreviousValue{...}) because pgfplotstable's \prevrow macro doesn't give access to values from the column being created, as it seems. If access to any previously-computed value in the column being created is desired, one could use a pgfmath array1 or an expl3 tl or seq variable, for instance.

\begin{filecontents*}{data.csv}
 x   y
 0   1
 5   6
10  11
\end{filecontents*}

\documentclass{article}
\usepackage{booktabs}
\usepackage{pgfplotstable}
\pgfplotsset{compat=1.16}

\pgfplotstableread[row sep=newline, col sep=space]{data.csv}\myTable

\newcommand*{\myPreviousValue}{100} % initialization (row -1, sort of)

% Dynamically create column z
\pgfplotstablecreatecol[
  create col/assign/.code={%
    \pgfmathsetmacro{\myValue}{int(\thisrow{y} + \myPreviousValue)}%
    \pgfplotstableset{create col/next content/.expand once={\myValue}}%
    \xdef\myPreviousValue{\myValue}%
  }]
{z}\myTable

\begin{document}

\pgfplotstabletypeset[
  columns/x/.style={column name={$x$}},
  columns/y/.style={column name={$y$}},
  columns/z/.style={column name={$z$}},
  every head row/.style={before row=\toprule, after row=\midrule},
  every last row/.style={after row=\bottomrule}
  ]{\myTable}

\end{document}

enter image description here

Note: the int() in the pgfmath expression I used might appear as unnecessary because by default, \pgfplotstabletypeset formats values using \pgfmathprintnumber and, again by default, \pgfmathprintnumber detects if the input has a fractional part equal to zero in order to special-case the printing of integers. For instance, \pgfmathprintnumber{118.0} prints 118 by default. However, without the int(), the values stored in \myValue—and thus also in the created in-memory column and in \myPreviousValue—would have a trailing .0; using the int() function prevents this.


Footnote

  1. Search the TikZ & PGF manual for “array access operators” in the Mathematical and Object-Oriented Engines part.
frougon
  • 24,283
  • 1
  • 32
  • 55
  • Oh, that looks pretty nice just three little questions: in the line \pgfmathsetmacro{\myValue}{int(\thisrow{y} + \myPreviousValue)}% what does the int() do? Is this some kind of "cast" of the result?

    Is there another way to insert tables from pgfplotstables to pgfplots without macros (I suppose not or is there one?)

    And the last one, just curious is there a specific reason why people add a % at the end of the line?

    – atticus Mar 20 '20 at 16:42
  • int() is used to obtain an integer, otherwise \pgfmathparse and \pgfmathsetmacro produce floating point results (try \show\myValue in my code after the \pgfmathsetmacro line. 2) The table data can very easily be turned into a plot, e.g. with \usepackage{pgfplots} and `\begin{tikzpicture}
  • \begin{axis} \addplot3[color=blue, only marks] table[x=x, y=y, z=z] {\myTable}; \end{axis} \end{tikzpicture}` in my sample document.

    – frougon Mar 20 '20 at 16:54
  • The end-of-line percent signs are very important in many contexts to avoid spurious spaces. In some contexts, they are not necessary: e.g., between comma-separated options when using PGF keys, TikZ options...
  • – frougon Mar 20 '20 at 16:54
  • ok so as I already suspected.

  • yea this is what I meant by inserting my macro (but I don't know a way doing this without it)

  • Oh didn't knew that

  • – atticus Mar 20 '20 at 17:02