2

This question already has an answer here:

The labeling of the bars is sometimes behind the error bar. Lifting them all isn't elegant but I haven't found a way to adjust the positions of the individual nodes. I included the third set of bars just to show that not all bars are not labeled (if that would make a difference). Perhaps there is another way of setting the labels than the nodes near coord and point meta.

      \documentclass{book}
      \usepackage{caption}
      \usepackage{pgfplots}
      \usepackage{booktabs}
      \usepackage{pgfplotstable}

      \begin{document}
      \definecolor{gray}{cmyk}{0,0,0,0.1}
      \definecolor{gray1}{cmyk}{0,0,0,0.3}
      \definecolor{gray2}{cmyk}{0,0,0,0.5}
      \definecolor{gray3}{cmyk}{0,0,0,0.7}

      \begin{figure}[htb]
      \begin{minipage}{\textwidth}
      \pgfplotstableread{
       x    y1  y1_err  y2  y2_err  y3  y3_err  y4  y4_err meta1 meta2 meta3 meta4
       A    100 0.1 100 0.1 81  7   87  5 a a b b 
       B    100 0.1 100 0.1 83  8   97  2 a a b a 
       C    84  2   87  2   86  4   93  1 \phantom{} \phantom{} \phantom{} \phantom{} 
        }\loadedtable
        \pgfplotsset{width=18cm,compat=1.9}
        \centering
        \begin{tikzpicture}
        \begin{axis}[ybar,
        ylabel={\%}, 
        symbolic x coords={A,B,C},
        xtick={A,B,C},
        ymin=0,
        ymax=110,
        nodes near coords, 
        every node near coord/.append style={yshift=0.2cm},    
        point meta=explicit symbolic,  
        ]
        \addplot+[error bars/.cd,
        y dir=both,
        y explicit
        ][black,fill=gray]table[
        meta index=9,
        x=x,
        y=y1,
        y error=y1_err,
        ]{\loadedtable};
        \addplot+[error bars/.cd,
        y dir=both,
        y explicit
        ][black,fill=gray1]table[
        meta index=10,
        x=x,
        y=y2,
        y error=y2_err,
        ]{\loadedtable};
        \addplot+[error bars/.cd,
        y dir=both,
        y explicit
        ][black,fill=gray2]table[
        meta index=11,
        x=x,
        y=y3,
        y error=y3_err,
        ]{\loadedtable};
        \addplot+[error bars/.cd,
        y dir=both,
        y explicit
        ][black,fill=gray3]table[
        meta index=12,
        x=x,
        y=y4,
        y error=y4_err,
        ]{\loadedtable};
       \end{axis}
      \end{tikzpicture}
     \end{minipage}
    \end{figure}
    \end{document}

marked as duplicate by Stefan Pinnow, Reinstate Monica - M. Schröder, user13907, Mico, barbara beeton Jan 27 '17 at 14:16

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

1

The main technique to do this is to use the key visualization depends on read in the error value do some computations on it and save the result in a macro, e.g. \myshift. Then you can shift each node by \myshift. As your error data comes from different columns the visualization depends on needs to added to each plot when you load the table. I have chosen to multiply the error by a fixed factor (4) to determine the shift; you may wish to use a different algorithm.

Sample output

\documentclass{book}

\usepackage{caption}
\usepackage{pgfplots}
\usepackage{booktabs}
\usepackage{pgfplotstable}
\usepackage{filecontents}

\pgfplotsset{compat=1.14}

\begin{document}
\definecolor{gray}{cmyk}{0,0,0,0.1}
\definecolor{gray1}{cmyk}{0,0,0,0.3}
\definecolor{gray2}{cmyk}{0,0,0,0.5}
\definecolor{gray3}{cmyk}{0,0,0,0.7}

\begin{filecontents}{mytab.dat}
x y1 y1_err y2 y2_err y3 y3_err y4 y4_err meta1 meta2 meta3 meta4
A 100 0.1 100 0.1 81 7 87 5 a a b b
B 100 0.1 100 0.1 83 8 97 2 a a b a
C 84 2 87 2 86 4 93 1 {} {} {} {}
\end{filecontents}

\begin{figure}[htb]
  \begin{minipage}{\textwidth}
    \pgfplotsset{width=18cm}
    \centering
    \begin{tikzpicture}
      \begin{axis}[ybar,
        ylabel={\%},
        symbolic x coords={A,B,C},
        xtick={A,B,C},
        ymin=0,
        ymax=110,
        nodes near coords,
        nodes near coords style={yshift=\myshift},
        point meta=explicit symbolic,
        ]
        \addplot+[error bars/.cd,
        y dir=both,
        y explicit][black,fill=gray]table[
        meta index=9,
        x=x,
        y=y1,
        y error=y1_err,
        visualization depends on=4*\thisrow{y1_err} \as \myshift,
        ] {mytab.dat};
        \addplot+[error bars/.cd,
        y dir=both,
        y explicit ][black,fill=gray1]table[
        meta index=10,
        x=x,
        y=y2,
        y error=y2_err,
        visualization depends on=4*\thisrow{y2_err} \as \myshift,
        ]{mytab.dat};
        \addplot+[error bars/.cd,
        y dir=both,
        y explicit ][black,fill=gray2]table[
        meta index=11,
        x=x,
        y=y3,
        y error=y3_err,
        visualization depends on=4*\thisrow{y3_err} \as \myshift,
        ]{mytab.dat};
        \addplot+[error bars/.cd,
        y dir=both,
        y explicit ][black,fill=gray3]table[
        meta index=12,
        x=x,
        y=y4,
        y error=y4_err,
        visualization depends on=4*\thisrow{y4_err} \as \myshift,
        ]{mytab.dat};
      \end{axis}
    \end{tikzpicture}
  \end{minipage}
\end{figure}
\end{document}

It seems to be a bug, as I could only get the \thisrow macro to work with table data in an external file. Putting the table in a macro and passing that as in your original code just fails.

Note that blank entries in your table data should be simply {}.

Not the answer you're looking for? Browse other questions tagged or ask your own question.