1

I have a 3-column datafile where the first column specifies the paramter and the other two shall be the x and y coordinates of the respective curve. How can I make sure that curves of different parameter aren't connected and can ideally be uniquely labeled and/or colored?

I know I could use gnuplot or split up the datafile in multiple columns/files as mentioned in a similar question but I have a few hundred different parameters so I was hoping pgfplots would either allow me to filter out for each plot the coordinates that don't match their parameter or directly plot this datafile with multiple curves.

e.g.

\documentclass[preview]{standalone}
    \usepackage{pgfplots}
    \pgfplotsset{compat=newest}

    \begin{filecontents}{data.dat}
        1 0   0.5
        1 1   1
        1 2   1.5
        2 0   0
        2 0.5 0.5
        2 1   0.75
        2 1.5 0.865
    \end{filecontents}

    \usepackage{tikz}
    \begin{document}
        \begin{tikzpicture}
            \begin{axis}[]
            \addplot table[x index=1, y index=2]{data.dat};
            \end{axis}
        \end{tikzpicture}
    \end{document}

Produces A single connected plot ,but I want one plot per parameter

1

Here is a proposal. I've adapted this answer from How to read a specific portion of a data file in pgfplots.

Use discard if not={<-parameter-col-num->}{<-parameter-value->}.

You mention that you have a few hundred parameters, so you could use a foreach loop such as:

\foreach \N in {1,2}{
\addplot table[x index=1, y index=2,discard if not={0}{\N}]{data.dat};
}

See the bottom of this post for a larger example using 5 parameters.

enter image description here

MWE

\documentclass[margin=0.5cm]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}

\begin{filecontents}{data.dat} % data format: | Parameter | X | Y |
        1 0   0.5
        1 1   1
        1 2   1.5
        2 0   0
        2 0.5 0.5
        2 1   0.75
        2 1.5 0.865
\end{filecontents}

% Adapted from https://tex.stackexchange.com/a/178632/128068
% Changed \thisrow{#1} to \thisrowno{#1}        
\pgfplotsset{
    discard if not/.style 2 args={
        x filter/.code={
            \edef\tempa{\thisrowno{#1}}
            \edef\tempb{#2}
            \ifx\tempa\tempb
            \else
                \def\pgfmathresult{inf}
            \fi
        }
    }
}

\begin{document}
    \begin{tikzpicture}
        \begin{axis}[]
        \addplot table[x index=1, y index=2,discard if not={0}{1}]{data.dat};
        \addplot table[x index=1, y index=2,discard if not={0}{2}]{data.dat};
        \end{axis}
    \end{tikzpicture}
\end{document}

Here is an example of foreach with a larger data file of 5 parameters:

enter image description here

\documentclass[margin=0.5cm]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}

\begin{filecontents}{data.dat} % data format: | Parameter | X | Y |
        1 0   0.5
        1 1   1
        1 2   1.5
        2 0   0
        2 0.5 0.5
        2 1   0.75
        2 1.5  0.865
        3 0   1.5
        3 1   2.6
        3 2   1.9
        4 0   4
        4 0.5 3.7
        4 1    3.6
        5 1.5 4.865
        5 2 2.5
\end{filecontents}

% Adapted from https://tex.stackexchange.com/a/178632/128068
% Changed \thisrow{#1} to \thisrowno{#1}       
\pgfplotsset{
    discard if not/.style 2 args={
        x filter/.code={
            \edef\tempa{\thisrowno{#1}}
            \edef\tempb{#2}
            \ifx\tempa\tempb
            \else
                \def\pgfmathresult{inf}
            \fi
        }
    }
}

\begin{document}
    \begin{tikzpicture}
        \begin{axis}[]
        \foreach \N in {1,...,5}{
        \addplot table[x index=1, y index=2,discard if not={0}{\N}]{data.dat};
        }
        \end{axis}
    \end{tikzpicture}
\end{document}
  • It's essentially what I was looking for, however too slow and memory consuming, going OOM (! TeX capacity exceeded, sorry [main memory size=5000000]) at around 50 curves. Also, curiously, starting from the 5th curve, even if I only plot 5, not all datapoints will be plottet resulting in gaps within a curve. I'll try to color the curves using meta/mesh plot. – Gamification Aug 29 '18 at 21:53
  • Does all your data plot quickly (albeit as one giant data set) when you don't use the code from this answer? – Milo Aug 29 '18 at 22:01
  • As one giant dataset a minimal pdflatex run is 1.14s , for {1,...,8}, it's 3.88s, for {1,...,16} 10.96s – For reference, a minimal plot like above is 0.43s – Gamification Aug 29 '18 at 22:12
  • Maybe this is the solution - see tex.stackexchange.com/questions/236398/… – Milo Aug 29 '18 at 22:17
  • "the table is being read from disk at every iteration of the for loop. To read the table once, use \pgfplotstableread" – Milo Aug 29 '18 at 22:18
0

It's not the perfect solution because it requires a change to the datafiles and misuses colormaps for curve colors. unbounded coords=jump as axis parameter will interrupt the plot when nan inf or -inf appears in the datafile (sec. 4.4.10 of the pgfplots manual)

So the curves can be separated using a line of NaNs whenever the parameter changes.

    1 2   1.5
    NaN NaN NaN
    2 0   0

yay, the two curves aren't connected anymore

The parameter can be color-coded using meta and colormaps

\addplot[mesh, point meta = \thisrowno{0}] table[x index=1, y index=2]{data.dat};

It is now a mesh plot, for colored points – instead or in addition – a scatter plot can be used.

they're colored

The colormap will stretch over the range of parameters which can make single curves hard to differentiate. point meta = {mod(\thisrowno0,8)} will alternate the colors every 8 paramters.

Put together:

\documentclass[preview]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}

\begin{filecontents}{data.dat}
    1 0   0.5
    1 1   1
    1 2   1.5
    NaN NaN NaN
    2 0   0
    2 0.5 0.5
    2 1   0.75
    2 1.5 0.865
\end{filecontents}

\usepackage{tikz}
\begin{document}
    \begin{tikzpicture}
        \begin{axis}[unbounded coords=jump]
        \addplot[mesh, scatter, point meta = {mod(\thisrowno0,8)}] table[x index=1, y index=2]{data.dat};
        \end{axis}
    \end{tikzpicture}
\end{document}

enter image description here

  • Wondering if it would be possible to use the palette instead of (or as) a colormap for consistency. – Gamification Aug 30 '18 at 16:45
  • Could you also here repeat your computation times for 128 parameters with and without using \pgfplotstableread, please. – Stefan Pinnow Sep 2 '18 at 5:12
  • A palette (assuming you mean colorbar as palette) is also a colormap, but only allows certain values. Or what do you mean? – Stefan Pinnow Sep 2 '18 at 5:13
  • Ah, nevermind. Setting any palette will work, just the default colors for plots and colormaps differ. – Gamification Sep 4 '18 at 11:44
0

Not modifying the data file

This is more or less an advanced answer of Milo's answer, which is adapted to make all the computations in Lua -- when compiling with LuaLaTeX -- instead of in TeX together with the also already mentioned tip to read the whole table only once using \pgfplotstableread (from the pgplotstable package) instead of for each \addplot command. I have not tested if this really improves compilation speed, but would guess so.

Modifying the data file

In general I would recommend to restructure the data file. If all parameter modifications where calculated with the same amount of data points then you can have them all in one data file. Further depending if the computations were done at the same x coordinates you can have one x column and then all the y columns or pairwise. (Again, this only works if all columns have the same amount of rows. If they don't, you could fill the rest with NaNs.)

Or you can store each parameter variation in its own data file (of course.)

With that also "maintenance" is much easier, especially if you do not want to plot all the "hundreds of variations" in one plot -- which most likely also is not a good idea.

% used PGFPlots v1.16
    % (borrowed modified data file from Milo's answer
    %  <https://tex.stackexchange.com/a/448407/95441>)
    \begin{filecontents}{data.dat}
        % data format: | Parameter | X | Y |
        1 0   0.5
        1 1   1
        1 2   1.5
        2 0   0
        2 0.5 0.5
        2 1   0.75
        2 1.5  0.865
        3 0   1.5
        3 1   2.6
        3 2   1.9
        4 0   4
        4 0.5 3.7
        4 1    3.6
        5 1.5 4.865
        5 2 2.5
    \end{filecontents}
\documentclass[margin=5pt]{standalone}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
    % use this `compat' level or higher to make use of Lua for computations
    % when using LuaLaTeX
    \pgfplotsset{compat=1.12}
    \pgfplotstableread{data.dat}{\loadedtable}
\begin{document}
\begin{tikzpicture}
    \begin{axis}[
        % because we know we want to filter data points
        % we don't need a warning for every filtered data point in the log
        filter discard warning=false,
    ]
        \foreach \i in {1,...,5}{
            \addplot table [
                x expr={
                    ifthenelse(
                        \thisrowno{0} == \i,
                        \thisrowno{1},
                        NaN
                    )
                },
                y index=2,
            ] {\loadedtable};
        }
    \end{axis}
\end{tikzpicture}
\end{document}

image showing the result of above code

  • The numbers and x positions of datapoints greatly differ for different parameters (from a few dozens down to only two) – Gamification Aug 30 '18 at 18:24
  • Would you be so kind to repeat the calculations you did for Milo's answer and post the results here. So we can get an impression on the computation speeds from the same machine. (Please also do the "old" calculations again to confirm that they have not drastically changed.) – Stefan Pinnow Aug 30 '18 at 18:30
  • And do you really plot hundreds of parameters in one plot? And in your answer you would get the same colors every 8 parameters. (Using /colormap/Paired from the colorbrewer library would at least extend this to 12.) How can you distinguish which color belongs to which parameter without any other hints/information? – Stefan Pinnow Aug 30 '18 at 18:32
  • I'll be looking into the runtimes of lualatex/lualatex+pgfplotstableread. I am indeed currently plotting 1024 curves using my solution below but most of them consist of only two points. My plots are similar to (commons.wikimedia.org/wiki/File:GolombCodeRedundancy.svg). I could easily update my generator to produce a single curve for all large parameters but my solution below works fine and a gnuplot solution was somewhat ok performance wise (I've developed an aversion against gnuplot). I did not yet look into using a palette instead of or as a colormap as b/w print is top priority – Gamification Aug 30 '18 at 22:08
  • I'm not yet sure if I replace the color version I have created using gnuplot. There, I have used colored labels for some curves but the parameter is kind of clear because they're successively increasing so the color is primarily to depict the boundaries of single curves and the association of a label to a specific curve. – Gamification Aug 30 '18 at 22:13

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.