1

This is a follow up question to: PGFPLOTS: Drawings inside a bar of a barplot

I created a stack bar plot with coordinates at the bars such that I can draw arrows and other stuff inside the bar arranged at this coordinates. The following solution works fine as long as I only have one row:

\documentclass[border=5pt]{standalone}
\usepackage{pgfplots}
    \usetikzlibrary{arrows.meta}
    \pgfplotsset{
        compat=1.16,
        % define a style to use for the connecting lines
        /tikz/my line style/.style={
            black,
            thick,
            ->,
        },
    }
\begin{document}
\begin{tikzpicture}
    \begin{axis}[
        xbar stacked,
        width=8cm,
        height=2cm,
        symbolic y coords={naive},
        ytick=data,
        yticklabels={Naive},
        xlabel={Runtime [s]},
        legend columns=3,
        legend style={
            at={(0.5,1.05)},
            anchor=south,
            legend cell align=left,
            align=left,
            legend plot pos=left,
            draw=black,
            font=\footnotesize,
        },
        % !!! this is the critical point !!!
        % to make that solution work you have set the following option due to
        % technical reasons which is roughly:
        % normally the markers are first collected and are drawn *after*
        % `\end{axis}', in contrast to the `\draw' command. Said that, the
        % named `nodes near coords' are not available during the execution of
        % the `\draw' command
        clip marker paths=true,
    ]
        % draw the connecting lines using the predefined style
        \draw [my line style] (b-1-0) edge (a-0-1)
                                      edge (a-1-1)
        ;

        \addplot+[green] coordinates {(100,naive)}
            coordinate (a-\plotnum-\coordindex)
        ;
            \addlegendentry{Pre computations}

        \addplot+[
            yellow,
            nodes near coords,
            node near coords style={
                black,
                font=\small\bfseries,
                % also add names to the `nodes near coords`
                name=b-\plotnum-\coordindex,
            },
        ] coordinates {(900,naive)}
            % add coordinates to the points/bars
            coordinate (a-\plotnum-\coordindex)
        ;
            \addlegendentry{Iteration}

        \addplot+[red] coordinates {(150,naive)};
            \addlegendentry{Post computations}
    \end{axis}
\end{tikzpicture}
\end{document}

This results in: enter image description here

Now I want to add more rows. Therefore, I added more symbolic y coordinates:

symbolic y coords={naive, opt1, opt2}

to the axis options and then tried:

           \addplot+[green] coordinates {
                         (100,naive) (120,opt1) (125,opt2)
                }
                coordinate (a-\plotnum-\coordindex)
            ;
                \addlegendentry{Pre computations}

            \addplot+[
                yellow,
                nodes near coords,
                node near coords style={
                    black,
                    font=\small\bfseries,
                    % also add names to the `nodes near coords`
                    name=b-\plotnum-\coordindex,
                },
            ] coordinates {(900,naive)(800,opt1) (725,opt2)}
                % add coordinates to the points/bars
                coordinate (a-\plotnum-\coordindex)
            ;
                \addlegendentry{Iteration}

            \addplot+[red] coordinates {(150,naive)(120,opt1) (90,opt2)};
                \addlegendentry{Post computations}

This fails with the error that my (a-0-1) so no longer found. How can I automatically define a tikz coordinate for each key-value pair in the coordinates-list?

4

Here the modified code. To find out, how it works, please have a look at the comments in the code.

% used PGFPlots v1.16
\documentclass[border=5pt]{standalone}
\usepackage{pgfplotstable}
    \usetikzlibrary{arrows.meta}
    \pgfplotsset{
        compat=1.16,
        % define a style to use for the connecting lines
        /tikz/my line style/.style={
            black,
            thick,
            ->,
        },
    }
\begin{document}
\begin{tikzpicture}
        % moved data to a table
        \pgfplotstableread{
            y       x1  x2  x3
            naive   100 900 150
            opt1    120 800 120
            opt2    125 725 90
        }{\loadedtable}
            % store number of rows in the table
            \pgfplotstablegetrowsof{\loadedtable}
            \pgfmathtruncatemacro{\N}{\pgfplotsretval-1}
    \begin{axis}[
        xbar stacked,
        width=8cm,
        % ---------------------------------------------------------------------
        % adjusted or added stuff
        % ---------------------------------------------------------------------
        % so the bars don't overlap
        height=4cm,
        % so there is no free negative space
        xmin=0,
        % so there is some free space left above and below the bars
        % (otherwise it could be that some parts of the upper and lower bar
        %  are clipped at the axis limits)
        enlarge y limits={abs=0.5},
        % (just use the coordinate index as y position ...
        table/y expr={\coordindex},
        % ... use as labels the `y` column of the data table ...
        yticklabels from table={\loadedtable}{y},
        % ---------------------------------------------------------------------
        % (and state them at the data points (of the first `\addplot` command)
        ytick=data,
        xlabel={Runtime [s]},
        legend columns=3,
        legend style={
            at={(0.5,1.05)},
            anchor=south,
            legend cell align=left,
            align=left,
            legend plot pos=left,
            draw=black,
            font=\footnotesize,
        },
        % !!! this is the critical point !!!
        % to make that solution work you have set the following option due to
        % technical reasons which is roughly:
        % normally the markers are first collected and are drawn *after*
        % `\end{axis}', in contrast to the `\draw' command. Said that, the
        % named `nodes near coords' are not available during the execution of
        % the `\draw' command
        clip marker paths=true,
    ]
        % draw the connecting lines using the predefined style
        \pgfplotsinvokeforeach {0,...,\N} {
            \draw [my line style] (bb#1) edge (a#1)
                                         edge (b#1)
            ;
        }

        \addplot+[green] table [x=x1] {\loadedtable}
            \foreach \i in {0,...,\N} {
                coordinate [pos=\i/\N] (a\i)
            }
        ;
        \addlegendentry{Pre computations}

        \addplot+[
            yellow,
            nodes near coords,
            node near coords style={
                blue,
                font=\small\bfseries,
                % also add names to the `nodes near coords`
                name=bb\coordindex,
            },
        ] table [x=x2] {\loadedtable}
            % add coordinates to the points/bars
            \foreach \i in {0,...,\N} {
                coordinate [pos=\i/\N] (b\i)
            }
        ;
        \addlegendentry{Iteration}

        \addplot+[red] table [x=x3] {\loadedtable};
        \addlegendentry{Post computations}
    \end{axis}
\end{tikzpicture}
\end{document}

image showing the result of above code

| improve this answer | |
  • Thanks alot. This is what I was looking for :-) – M.K. aka Grisu Apr 1 at 12:35

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.