0

I'm trying to make a bar plot showing the runtime of some programs and I would like to have some of the bar plots run off the top of the page. Currently, I do this by setting the values of the bars to be something large (see example below--for Program 1 the rightmost bar plot for Test 3 has value 10 but I want it to go off the page) but I actually want the bars to scale to the height of the bar graph and go off the top of the page. I also want the label T.O. (timeout) to be on top of the blue bar on the right but currently it is between the blue and right bars on the right (see example below). Is there any way to put the T.O. label on the rightmost blue bar instead of in the middle of the blue and red bars?

Here is my code:

\begin{figure*}
\begin{tikzpicture}
\begin{axis}[
    ylabel=Seconds,
    ymode=log,
    bar width=10pt,
    ybar,
    x tick label style={rotate=25},
    symbolic x coords={Test 1, Test 2, Test 3},
    xtick=data,
    legend pos = north west,
    height=7cm,
    width=\textwidth,
]
\addplot
    coordinates {
        (Test 1, 0.4)
        (Test 2, 1.5)
        (Test 3, 10)
};
\node[above] at (axis cs:Test 3, 10) {T.O.};
\addplot
    coordinates {
        (Test 1, 5.5)
        (Test 2, 4.6)
        (Test 3, 6)
};
\legend{Program 1, Program 2}
\end{axis}
\end{tikzpicture}
\caption{Program Runtimes}
\end{figure*}

Here is what the bar plot looks like in my file:

enter image description here

Here is what I want the bar plot to look like:

enter image description here

Is this possible?

0

You can set the range of the y axis manually using ymax and then set the timed out bar to this value. This causes the bar to extend to the edge of the plot without the plot area being enlarged.

To print a node outside the plot area you can use clip=false. To prevent the tick mark to overlap with the label you can switch off the top tick marks using xtick pos=left. You can shift the label a bit left using xshift to center it above the bar.

Furthermore I needed to set log origin=infty to make sure the bars start at the bottom of the graph.

MWE:

\documentclass{article}
\usepackage{pgfplots}
\begin{document}
\begin{figure*}
\begin{tikzpicture}
\begin{axis}[
    ylabel=Seconds,
    ymode=log,
    log origin=infty,
    bar width=10pt,
    ybar,
    x tick label style={rotate=25},
    symbolic x coords={Test 1, Test 2, Test 3},
    xtick=data,
    legend pos = north west,
    height=7cm,
    width=\textwidth,
    ymax=15,
    clip=false,
    xtick pos=left,
]
\addplot
    coordinates {
        (Test 1, 0.4)
        (Test 2, 1.5)
        (Test 3, 15)
};
\node[above,xshift=-5pt] at (axis cs:Test 3, 15) {T.O.};
\addplot
    coordinates {
        (Test 1, 5.5)
        (Test 2, 4.6)
        (Test 3, 6)
};
\legend{Program 1, Program 2}
\end{axis}
\end{tikzpicture}
\end{figure*}
\end{document}

Result:

enter image description here

References that I used for this answer:

pgfplots and log scale: bars starting from the bottom of the screeen

Long node undesiringly cropped outside of pgfplot

How to remove ticks from the top and right axes of a plot generated with PGFPlots?

2

Here I present a modified solution of my answer https://tex.stackexchange.com/a/365826/95441 to make it work for log plots as well. This has the advantage that to all bars exceeding ymax will get the text "automatically". For details please have a look the comments in the code.

% used PGFPlots v1.18.1
% (modified version of <https://tex.stackexchange.com/a/365826/95441>)
\documentclass[border=5pt]{standalone}
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture}
        % create a variable to store the `ymax' value
        \pgfmathsetmacro{\ymax}{15}
    \begin{axis}[
        ymode=log,
        % (plot all bars from bottom (i.e. from the bottom axis line))
        log origin=infty,
        ybar,
        symbolic x coords={Test 1, Test 2, Test 3},
        xtick=data,
        % use the previously created variable here
        ymax=\ymax,
        % (this i just added so the outer most bars aren't clipped partially)
        enlarge x limits={0.2},
        % -----------------------------------------------------------------
        % we only want to print some text ...
        nodes near coords={T.O.},
        % ... when the y value is greater than `ymax`
        % (it is `ln` instead of `log10` because internally logarithmic values
        %  are calculated on the basis $e$)
        y filter/.code={\pgfmathparse{min(ln(y),ln(\ymax))}},
        % ---------------------------------------------------------------------
        % now we create a style for the `nodes near coords` which is dependent
        % on the value
        % (adapted from <http://tex.stackexchange.com/a/141006/95441>)
        % (#1: the THRESHOLD after which we switch to a special display)
        nodes near coords greater equal only/.style={
            % define the style of the nodes with "small" values
            small value/.style={
                /tikz/coordinate,
            },
            every node near coord/.append style={
                check for small values/.code={
                    \begingroup
                    % this group is merely to switch to FPU locally.
                    % Might be unnecessary, but who knows.
                    \pgfkeys{/pgf/fpu}
                    \pgfmathparse{\pgfplotspointmeta<(#1)}
                    \global\let\result=\pgfmathresult
                    \endgroup
                    %
                    % simplifies debugging:
                    %\show\result
                    %
                    \pgfmathfloatcreate{1}{1.0}{0}
                    \let\ONE=\pgfmathresult
                    \ifx\result\ONE
                        % AH: our condition 'y < #1' is met.
                        \pgfkeysalso{/pgfplots/small value}
                    \fi
                },
                check for small values,
            },
        },
        % assign a value to the new style which is the threshold at which
        % the `small value' style is used.
        % Of course in this case it should be the logarithmic `\ymax' value
        nodes near coords greater equal only=ln(\ymax),
        % -----------------------------------------------------------------
    ]
        \addplot coordinates {(Test 1, 0.4) (Test 2, 1.5) (Test 3, 16)};
        \addplot coordinates {(Test 1, 5.5) (Test 2, 4.6) (Test 3,  6)};
    \end{axis}
\end{tikzpicture}
\end{document}

image showing the result of above code

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.