[Tex/LaTex] pgfplots – Create multiple plots from one table (rows 0–3, 4–7,…)

foreachpgfplots

Using JMH in java I have created file. Suppose .csv file looks like this (but far bigger):

"Benchmark","Mode","Threads","Samples","Score","Score Error (99.9%)","Unit","Param: capacity","Param: objects"
"com.group.name.lists.impl.GuavaArrayLists.testArrayList","thrpt",1,50,13840788.290265,340713.080893,"ops/s",0,1
"com.group.name.lists.impl.GuavaArrayLists.testArrayList","thrpt",1,50,308084.862046,3363.564803,"ops/s",0,100
"com.group.name.lists.impl.GuavaArrayLists.testArrayList","thrpt",1,50,32961.868917,400.213686,"ops/s",0,1000
"com.group.name.lists.impl.GuavaArrayLists.testArrayList","thrpt",1,50,3326.423048,29.662297,"ops/s",0,10000
"com.group.name.lists.impl.GuavaArrayLists.testArrayList","thrpt",1,50,14480091.281797,201352.449027,"ops/s",500,1
"com.group.name.lists.impl.GuavaArrayLists.testArrayList","thrpt",1,50,316558.184911,3352.761618,"ops/s",500,100
"com.group.name.lists.impl.GuavaArrayLists.testArrayList","thrpt",1,50,33562.619512,290.498672,"ops/s",500,1000
"com.group.name.lists.impl.GuavaArrayLists.testArrayList","thrpt",1,50,3319.397084,22.321262,"ops/s",500,10000
"com.group.name.lists.impl.GuavaArrayLists.testArrayList","thrpt",1,50,14501880.364073,116230.130746,"ops/s",10000,1
"com.group.name.lists.impl.GuavaArrayLists.testArrayList","thrpt",1,50,319336.611259,2659.178072,"ops/s",10000,100
"com.group.name.lists.impl.GuavaArrayLists.testArrayList","thrpt",1,50,33588.319651,243.878605,"ops/s",10000,1000
"com.group.name.lists.impl.GuavaArrayLists.testArrayList","thrpt",1,50,3322.992416,25.905451,"ops/s",10000,10000
"com.group.name.lists.impl.GuavaLinkedLists.testLinkedList","thrpt",1,50,19993525.187572,240143.948149,"ops/s",0,1
"com.group.name.lists.impl.GuavaLinkedLists.testLinkedList","thrpt",1,50,311584.596234,6280.931754,"ops/s",0,100
"com.group.name.lists.impl.GuavaLinkedLists.testLinkedList","thrpt",1,50,30846.002383,749.757479,"ops/s",0,1000
"com.group.name.lists.impl.GuavaLinkedLists.testLinkedList","thrpt",1,50,2942.108526,84.974577,"ops/s",0,10000

Is it possible to create plot for each n rows (eg. 0-3, 4-7, ..) in this table?

I'm beginner with pgf and quite so with LaTeX as well.. I did create some plots without cycle, but it would be most useful to have "automatic graph maker" that I would point in the .csv file and would be given graph.

I have combined How to draw a graph from CSV with TeX? , How to plot the first n rows of a table using pgfplots? and axis lable in millions/thousands but I cannot make

\documentclass[tikz]{standalone}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
\usepackage{siunitx}
\usepackage{graphicx}

\pgfplotsset{compat=1.5, width = 12cm, height = 5cm, select coords between index/.style 2 args={
    x filter/.code={
        \ifnum\coordindex<#1\def\pgfmathresult{}\fi
        \ifnum\coordindex>#2\def\pgfmathresult{}\fi
    }
}}
\begin{document}
    \begin{tikzpicture}
        \begin{axis}[/pgfplots/error bars/.cd, x dir = normal, y dir = normal, x explicit, y explicit,title=Lists collections performance,
                    xlabel = Objects,
  legend style={legend columns=-1},
  legend to name={thelegend},
  name={theaxis},
                    ylabel = Add operations ops/s,      
                    y tick label style={ytick scale label code/.code={}, scaled y ticks=base 10:-6, yticklabel={\pgfmathprintnumber{\tick} million},},
                x tick label style={/pgf/number format/.cd, scaled x ticks = false, set decimal separator={,}, fixed},
                    xmin = 1, xmax = 10000,
            ]{lists-results.csv}
        \addplot+[red, mark = o, ultra thick,] [select coords between index={0}{3}]
        table [col sep=comma, ignore chars=\%, x="Param: objects", y="Score",]{lists-results.csv};
        \addplot+[blue, mark = o, thick] [select coords between index={4}{7}]
        table [col sep=comma, ignore chars=\%, x="Param: objects", y="Score",]{lists-results.csv};
        \addplot+[green, mark = o] [select coords between index={8}{11}]
        table [col sep=comma, ignore chars=\%, x="Param: objects", y="Score",]{lists-results.csv};
        \addplot+[purple, mark = o] [select coords between index={12}{15}]
        table [col sep=comma, ignore chars=\%, x="Param: objects", y="Score",]{lists-results.csv};
        \legend{Guava ArrayList(0), Guava ArrayList(500), Guava ArrayList(10000), Guava LinkedList}
        \end{axis}
\node [below] at (theaxis.below south) {\ref{thelegend}};
    \end{tikzpicture}
\end{document}

I have tried something like this, but it doesn't seem to be working

\foreach \n in {0,4...,28}{
    \addplot+[red, mark = o] [select coords between index={\n}{\n+3}]
      table [col sep=comma, ignore chars=\%, x="Param: objects", y="Score",]
       {lists-results.csv};
}

Additional (marginal) questions would be:

1) Is it possible to shorten the names of Benchmarks?
like "com.group.name.lists.impl.GuavaLinkedLists.testLinkedList" -> "GuavaLinkedLists"

2) Is it possible to add to the name number from other column?
like Benchmarks:"GuavaLinkedLists" and Param: capacity":0 ->"GuavaLinkedLists(0)"

3) Is it possible to multiply two columns to create x axis numbers?
like "Score":3326.423048 and "Param: objects":10000 -> 33264230.48
Is it possible to multiply the x coordinates of a plot by a certain factor using pgfplots

4) How to distribute each column value equally?
Horizontal space between xticks in pgfplots

5) How to create horizontal lining?
Horizontal lines in bar plots without first line

6) How to export pdf in console?
How to create pdf with command line using MiKTeX?

Best Answer

Yes, this is possible. The main problem, why your \foreach solution isn't working is, because the \n+3 isn't evaluated. You can test this by, e.g. replacing select coords between index={12}{15} with select coords between index={12}{12+3} in your "manual" solution, which will raise an error.

I think I also have addressed all your "additional (marginal) questions" except for the last two. Regarding 5) I don't like grid lines, but you already have found the solution so I think you can apply that yourself if you really want/need them. And Regarding 6) I am not sure if you really just meant to output a PDF of "the whole document" or maybe just create a PDF of the plot (alone).

For more details please have a look at the comments in the code.

% used PGFPlots v1.14
\documentclass[border=5pt]{standalone}
\usepackage{xstring}        % <-- needed for string manipulation
\usepackage{pgfplots}
\usepackage{pgfplotstable}
    \pgfplotsset{
        % use at least this `compat' level to improve placing of axis labels
        compat=1.3,
        % (almost the) opposite of `skip coords between index'
        % only use x values when the `\coordindex' lays between the two
        % arguments (including), else "skip" them by setting the value to "NaN"
        select coords between index/.style 2 args={
            x filter/.code={
                \pgfmathifthenelse{or(\coordindex<#1,\coordindex>#2)}{NaN}{x}
                \pgfmathresult
            },
        },
        table/col sep=comma,
        table/ignore chars=\%,
    }
    % define a command to create the legend entries
    % (give the row number to the argument)
    \newcommand{\CustomLegend}[1]{
        % store the "Benchmark" entry of the given row number in `\Benchmark'
        \pgfplotstablegetelem{#1}{"Benchmark"}\of{\table}
            \edef\Benchmark{\pgfplotsretval}
        % store the "Capacity" entry of the given row number in `\Capacity'
        \pgfplotstablegetelem{#1}{"Param: capacity"}\of{\table}
            \edef\Capacity{\pgfplotsretval}
        % create the legend entry
        \addlegendentryexpanded{
            % only use the part of `\Benchmark' between the given two strings
            \noexpand\StrBetween{\Benchmark}{impl.}{s.test}
            % append the capacity entry in brackets if the "Benchmark" entry
            % ends with the given string (else return an empty string)
            \noexpand\IfEndWith{\Benchmark}{ArrayList"}{%
                (\Capacity)
            }{}
        }
    }
\begin{document}
    \begin{tikzpicture}
            % read the table from the file
            \pgfplotstableread{lists-results.csv}{\table}
        \begin{axis}[
            title=Lists collections performance,
            xlabel=Objects,
            % changed y axis label and corresponding style
            ylabel=Add operations in million ops/s,
            % use an index for the data points and get the labels from the table
            xtick={0,...,10},
            xticklabels from table={\table}{"Param: objects"},
            y tick label style={
                ytick scale label code/.code={},
                scaled y ticks=base 10:-6,
            },
            % changed positioning of the legend
            legend pos=outer north east,
            % use left alignment for labels in legend
            legend cell align=left,
        ]
            \foreach \n in {0,4,...,12}{
                \addplot+[mark=o,select coords between index={\n}{\n+3}] table [
                % to avoid a numerical issue I have added "+0.1" to x
                % (otherwise for \n=16 the modulus would return 4, because
                % 16 would be something like 15.999)
                    x expr={int(mod(\coordindex + 0.1,4))},
                    y expr=\thisrow{"Score"}*\thisrow{"Param: objects"},
                ] {\table};
                    \CustomLegend{\n}
            }
        \end{axis}
    \end{tikzpicture}
\end{document}

image showing the result of above code

Related Question