1

What I want to do:
Put horizontal lines on top of every bar of a grouped bar plot with symbolic x axis coordinates. The lines shall align with the width of each bar. See the 2 example bars with lines in the code and the image below.
Note, that these lines are used to indicate an "upper bound" for each bar. Hence, every line has its own y-coordinate which is independent from the actual height of the bar.
What I have so far:
I only came up with an unsatisfying solution:
Draw simple lines by a \draw call and approximating the x-coordinates by hand.
Why is this a problem?
This leads to the very ugly "magic" numbers (e.g. !.655!, !.862!) for the x-coordinate calculation as you can see in the code below. This becomes very tedious since I have many bars and the number of bars per group may change.
What is missing to solve my problem?
I am looking for a more convenient way to calculate (or get) the min/max x-coordinates of the individual bars. With these coordinates which are indicated with black ticks in the image below, I can easily draw the desired lines.

My current approach is based on the following MWE:

\documentclass[11pt]{standalone}

\usepackage{tikz}
\usetikzlibrary{calc}

\usepackage{pgfplots}

\begin{document}

\begin{tikzpicture}
\begin{axis}[
    ybar,
    enlargelimits=0.15,
    ylabel={index},
    symbolic x coords={1982, 1990, 1999, 2006},
    legend style={at={(0.5,-0.15)},
    anchor=north,legend columns=-1},
    ]

\addplot coordinates {(1982, 1.78) (1990, 1.71) (1999, 1.68) (2006, 1.62)};
\addplot coordinates {(1982,  1.70) (1990, 1.62) (1999, 1.59) (2006, 1.64)};
\addplot coordinates {(1982, 2.04) (1990, 1.96) (1999, 1.95) (2006, 1.91)};

\draw[blue, thick] ($(axis cs:1982, 1.72)!.655!(axis cs:1990, 1.72)$) -- ($(axis cs:1982, 1.72)!.862!(axis cs:1990, 1.72)$);
\draw[red , thick] ($(axis cs:1982, 1.68)!.89!(axis cs:1990, 1.68)$) -- ($(axis cs:1990, 1.68)!.115!(axis cs:1999, 1.68)$);

\legend{USA, Netherlands, {(West-)Germany}}

\end{axis}
\end{tikzpicture}

\end{document}

Image

Any help is very appreciated.

edit: clarified question.

  • 1
    sorry, your question is unclear. what you like to acieve? numbers with $\overline$ on top of bars?. for conviniece, please provide code what you try so far (by which the plot in your question has been generated). – Zarko Feb 11 '18 at 1:11
1

So you are searching for something like the following?
For details please have a look at the comments of the code.

% used PGFPlots v1.15
\documentclass[border=5pt]{standalone}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
    \pgfplotsset{compat=1.3}
    % move data to a table
    % add columns for error bars and state "NaN" where no bar should be shown
    \pgfplotstableread{
        x       y1      y2      y3      y1err   y2err
        1982    1.78    1.70    2.04    NaN     NaN
        1990    1.71    1.62    1.96    0.05    0.02
        1999    1.68    1.59    1.95    NaN     NaN
        2006    1.62    1.64    1.91    NaN     NaN
    }{\loadedtable}
\begin{document}
\begin{tikzpicture}
    \begin{axis}[
        ybar,
        ylabel={index},
        % so you don't have to repeat the "x" data, replace the commented line
        % by the next two
        % (this only works if the first `\addplot' command has data points on
        %  all x coordinates)
%        symbolic x coords={1982, 1990, 1999, 2006},
        xtick=data,
        xticklabels from table={\loadedtable}{x},
        enlargelimits=0.15,
        legend style={
            at={(0.5,-0.15)},
            anchor=north,
            legend columns=-1,
        },
        % ---
        % moved common options here
        % ---
        % this is also needed for the replacement of `symbolic x coords'
        table/x expr=\coordindex,
        % now we add the horizontal lines
        error bars/y dir=plus,
        error bars/y explicit,
        % (inspired by <https://tex.stackexchange.com/a/19962/95441>)
        error bars/error bar style={
            % don't show the vertical line
            opacity=0,
        },
        % and here the modifications for the horizontal line
        error bars/error mark options={
            rotate=90,
            mark size=0.5*\pgfplotbarwidth,
            line width=0.4pt,   % this is the default line with
            line cap=rect,
            opacity=1,          % to revert the option from `error bar style'
        },
    ]

        \addplot table [y=y1,y error=y1err]   {\loadedtable};
        \addplot table [y=y2,y error=y2err]   {\loadedtable};
        \addplot table [y=y3]                 {\loadedtable};

        \legend{
            USA,
            Netherlands,
            {(West-)Germany},
        }
    \end{axis}
\end{tikzpicture}
\end{document}

image showing the result of above code

  • Yes, this is pretty much what I was looking for. A lot of error magic was required ;-). I only have minor issue now: my input data does not have these relative error values, but absolute values. For example the line from your dummy table would read like: 1990 1.71 1.62 1.96 1.76 1.64 So I am just gonna add new columns containing the calculated error and then everything should be fine :) Thanks a lot! – arox Feb 11 '18 at 12:50
  • 1
    When you have the absolute/max value you could replace y error=y1err by y error expr=\thisrow{y1err} - \thisrow{y1}, etc. to achieve the desired result. – Stefan Pinnow Feb 11 '18 at 13:03
1

OK, I looked at an older version of your question, for which I propose

\documentclass{article}

\usepackage{pgfplots}
\pgfplotsset{compat=newest}

\begin{document}

\begin{tikzpicture}
\begin{axis}[
    ybar,
    enlargelimits=0.15,
    ylabel={index},
    symbolic x coords={1982, 1990, 1999, 2006},
    %xtick=data,
    %tick label style={font=\footnotesize},
    legend style={at={(0.5,-0.15)},
    anchor=north,legend columns=-1},
    nodes near coords,
    every node near coord/.append style={font=\tiny},
    nodes near coords={\underline{\pgfmathprintnumber{\pgfplotspointmeta}}},
   nodes near coords align={vertical},
    ]
\addplot coordinates {(1982, 1.78) (1990, 1.71) (1999, 1.68) (2006, 1.62)};
\addplot coordinates {(1982,  1.70) (1990, 1.62) (1999, 1.59) (2006, 1.64)};
\addplot coordinates {(1982, 2.04) (1990, 1.96) (1999, 1.95) (2006, 1.91)};
\legend{USA, Netherlands, {(West-)Germany}}

\end{axis}
\end{tikzpicture}

\end{document}

enter image description here

EDIT: OK, now to version 2 (?) of your question:

\documentclass{article}

\usepackage{pgfplots}
\pgfplotsset{compat=newest}

\begin{document}

\begin{tikzpicture}
\begin{axis}[
    ybar,
    bar width=12pt,
    enlargelimits=0.15,
    ylabel={index},
    symbolic x coords={1982, 1990, 1999, 2006},
    %xtick=data,
    %tick label style={font=\footnotesize},
    legend style={at={(0.5,-0.15)},
    anchor=north,legend columns=-1},
    nodes near coords,
    every node near coord/.append style={font=\tiny},
    nodes near coords={\rule{12pt}{1pt}},
   nodes near coords align={vertical},
    ]
\addplot coordinates {(1982, 1.78) (1990, 1.71) (1999, 1.68) (2006, 1.62)};
\addplot coordinates {(1982,  1.70) (1990, 1.62) (1999, 1.59) (2006, 1.64)};
\addplot coordinates {(1982, 2.04) (1990, 1.96) (1999, 1.95) (2006, 1.91)};
\legend{USA, Netherlands, {(West-)Germany}}

\end{axis}
\end{tikzpicture}

\end{document}

enter image description here

The lengths of the \rule are chosen to coincide with the bar width.

  • I am sorry for my initially unprecise question. – arox Feb 11 '18 at 1:47
  • @arox OK, I added the hopefully correct answer. – user121799 Feb 11 '18 at 1:54
  • Thanks again for your help, but I am afraid, its not exactly what I was looking for. I added the following note to my question, which hopefully eliminates further unclarities: "Note, that these lines are used to indicate an "upper bound" for each bar. Hence, every line has its own y-coordinate which is independent from the actual height of the bar." – arox Feb 11 '18 at 9:18

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.