[Tex/LaTex] pgfplotstableread + addplot table: scale column for re-use

pgfmathpgfplotspgfplotstable

I get output files from a code and I want to display the output file with pgfplots. I want to create several different plots with the same files. Therefore, I read them in a macro with pgfplotstable.

I know that the first column contains the x-axis values in seconds. For the plots I want to change the x-axis unit to milliseconds for each and every plot. Currently, I am doing this by multiplying the x-axis value by a thousand for every addplot by x expr=\thisrowno{0}*1000. In my opinion this wastes memory and compile time.

Is it possible to scale the first column values already in the pgfplotstableread?

In this thread I found columns/0/.style={preproc/expr={##1*1000}} for pgfplotstabletypeset but I could not find a similar command to permanently modifiy the values inside \chartdata. I also had a look at write to macro for pgfplotstablesetbut could not make it work.

\documentclass{standalone}
\usepackage{filecontents}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\usepackage{pgfplotstable}

\begin{document}

\begin{filecontents}{chartdata.txt}
time               value_1            value_2            value_3
s                  some_unit          some_unit          some_unit
0.                 0.                 0.                 0.         
100.E-09            27.541E-06        580.194E-09         19.8912E-06 
200.E-09            55.082E-06          1.18929E-06       40.2063E-06 
350.E-09            96.3935E-06         2.15546E-06       70.5431E-06 
575.E-09           158.361E-06          3.67572E-06      116.044E-06  
87.4788E-06        24.0925E-03       634.302E-06         17.6932E-03 
652.755E-06        179.775E-03          4.74164E-03      131.941E-03  
750.568E-06        206.714E-03         12.7344E-03       152.076E-03  
760.034E-06        209.321E-03         20.4248E-03       154.317E-03  
760.941E-06        209.571E-03         20.4985E-03       154.679E-03  
\end{filecontents}

\pgfplotstableread[
  skip first n=6, % 2+4 for filecontents header
]{chartdata.txt}{\chartdata}

\begin{tikzpicture}

  \begin{axis}[
    cycle list name=color list,
  ]
    \addplot+[
      % currenty no options
    ] table [
      x expr=\thisrowno{0}*1000,
      y expr=\thisrowno{1},
    ]{\chartdata};
    \addlegendentry{Value 1}
    \addplot+[
      % currenty no options
    ] table [
      x expr=\thisrowno{0}*1000,
      y expr=\thisrowno{2},
    ]{\chartdata};
    \addlegendentry{Value 2}
    \addplot+[
      % currenty no options
    ] table [
      x expr=\thisrowno{0}*1000,
      y expr=\thisrowno{3},
    ]{\chartdata};
    \addlegendentry{Value 3}
  \end{axis}
\end{tikzpicture}

\end{document}

Best Answer

You can create a new column

\pgfplotstablecreatecol
  [create col/expr={\thisrowno{0}*1000}]
  {time in ms}% column name
  \chartdata

and use it with x=time in ms in the plots.

\documentclass{standalone}
\usepackage{filecontents}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\usepackage{pgfplotstable}

\begin{document}

\begin{filecontents}{chartdata.txt}
time               value_1            value_2            value_3
s                  some_unit          some_unit          some_unit
0.                 0.                 0.                 0.         
100.E-09            27.541E-06        580.194E-09         19.8912E-06 
200.E-09            55.082E-06          1.18929E-06       40.2063E-06 
350.E-09            96.3935E-06         2.15546E-06       70.5431E-06 
575.E-09           158.361E-06          3.67572E-06      116.044E-06  
87.4788E-06        24.0925E-03       634.302E-06         17.6932E-03 
652.755E-06        179.775E-03          4.74164E-03      131.941E-03  
750.568E-06        206.714E-03         12.7344E-03       152.076E-03  
760.034E-06        209.321E-03         20.4248E-03       154.317E-03  
760.941E-06        209.571E-03         20.4985E-03       154.679E-03  
\end{filecontents}

\pgfplotstableread[
  skip first n=6, % 2+4 for filecontents header
]{chartdata.txt}{\chartdata}

\pgfplotstablecreatecol
  [create col/expr={\thisrowno{0}*1000}]
  {time in ms}% column name
  \chartdata

\begin{tikzpicture}
  \begin{axis}[
    cycle list name=color list,
  ]
    \addplot+[
      % currenty no options
    ] table [
      x=time in ms,
      y index=1,
    ]{\chartdata};
    \addlegendentry{Value 1}
    \addplot+[
      % currenty no options
    ] table [
      x=time in ms,
      y index=2,
    ]{\chartdata};
    \addlegendentry{Value 2}
    \addplot+[
      % currenty no options
    ] table [
      x=time in ms,
      y index=3,
    ]{\chartdata};
    \addlegendentry{Value 3}
  \end{axis}
\end{tikzpicture}
\end{document}

enter image description here


Another possibility is modifying the first column

\documentclass{standalone}
\usepackage{filecontents}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\usepackage{pgfplotstable}

\begin{document}

\begin{filecontents}{chartdata.txt}
time               value_1            value_2            value_3
s                  some_unit          some_unit          some_unit
0.                 0.                 0.                 0.         
100.E-09            27.541E-06        580.194E-09         19.8912E-06 
200.E-09            55.082E-06          1.18929E-06       40.2063E-06 
350.E-09            96.3935E-06         2.15546E-06       70.5431E-06 
575.E-09           158.361E-06          3.67572E-06      116.044E-06  
87.4788E-06        24.0925E-03       634.302E-06         17.6932E-03 
652.755E-06        179.775E-03          4.74164E-03      131.941E-03  
750.568E-06        206.714E-03         12.7344E-03       152.076E-03  
760.034E-06        209.321E-03         20.4248E-03       154.317E-03  
760.941E-06        209.571E-03         20.4985E-03       154.679E-03  
\end{filecontents}

\pgfplotstableread[
  skip first n=6, % 2+4 for filecontents header
]{chartdata.txt}{\chartdata}


\pgfplotstablemodifyeachcolumnelement{[index]0}\of\chartdata\as\cell{%
  \pgfkeys{/pgf/fpu=true}%
  \pgfmathparse{1000*\cell}%
  \pgfkeys{/pgf/fpu=false}%
  \edef\cell{\pgfmathresult}%
}%

\begin{tikzpicture}
  \begin{axis}[
    cycle list name=color list,
  ]
    \addplot+[
      % currenty no options
    ] table [
      x index=0,
      y index=1,
    ]{\chartdata};
    \addlegendentry{Value 1}
    \addplot+[
      % currenty no options
    ] table [
      x index=0,
      y index=2,
    ]{\chartdata};
    \addlegendentry{Value 2}
    \addplot+[
      % currenty no options
    ] table [
      x index=0,
      y index=3,
    ]{\chartdata};
    \addlegendentry{Value 3}
  \end{axis}
\end{tikzpicture}
\end{document}

enter image description here


A third possibility is scaling only the xtick labels using

scaled x ticks=false,
xticklabel={%
  \pgfmathparse{\tick*1000}%
  $\pgfmathprintnumber[fixed,precision=1]{\pgfmathresult}$%
}

as options for the axis environment.

\documentclass{standalone}
\usepackage{filecontents}
\usepackage{xintexpr}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\usepackage{pgfplotstable}

\begin{document}

\begin{filecontents}{chartdata.txt}
time               value_1            value_2            value_3
s                  some_unit          some_unit          some_unit
0.                 0.                 0.                 0.         
100.E-09            27.541E-06        580.194E-09         19.8912E-06 
200.E-09            55.082E-06          1.18929E-06       40.2063E-06 
350.E-09            96.3935E-06         2.15546E-06       70.5431E-06 
575.E-09           158.361E-06          3.67572E-06      116.044E-06  
87.4788E-06        24.0925E-03       634.302E-06         17.6932E-03 
652.755E-06        179.775E-03          4.74164E-03      131.941E-03  
750.568E-06        206.714E-03         12.7344E-03       152.076E-03  
760.034E-06        209.321E-03         20.4248E-03       154.317E-03  
760.941E-06        209.571E-03         20.4985E-03       154.679E-03  
\end{filecontents}

\pgfplotstableread[
  skip first n=6, % 2+4 for filecontents header
]{chartdata.txt}{\chartdata}

\begin{tikzpicture}
  \begin{axis}[
    cycle list name=color list,
    scaled x ticks=false,
    xticklabel={%
      \pgfmathparse{\tick*1000}%
      $\pgfmathprintnumber[fixed,precision=1]{\pgfmathresult}$%
    }
  ]
    \addplot+[
      % currenty no options
    ] table [
      x index=0,
      y index=1,
    ]{\chartdata};
    \addlegendentry{Value 1}
    \addplot+[
      % currenty no options
    ] table [
      x index=0,
      y index=2,
    ]{\chartdata};
    \addlegendentry{Value 2}
    \addplot+[
      % currenty no options
    ] table [
      x index=0,
      y index=3,
    ]{\chartdata};
    \addlegendentry{Value 3}
  \end{axis}
\end{tikzpicture}
\end{document}

Edit by krtek:

For values larger >16383.9998, e.g. for the y-axis use fpu engine:

scaled y ticks=false,
yticklabel={%
  \pgfkeys{/pgf/fpu=true}%
  \pgfmathparse{\tick*1000}%
  \pgfkeys{/pgf/fpu=false}
  $\pgfmathprintnumber[
    fixed,
    precision=1,
  ]{\pgfmathresult}$%
}