2

The following example results in two overlapping nodes (column 4 and 5 in row 0):

\documentclass{standalone}
\usepackage{pgfplots,pgfplotstable}

\pgfplotsset{%
  ,xmin=0%
  ,/tikz/font=\footnotesize%
  ,compat=1.11%
}
\begin{document}

\pgfplotstableread[col sep=comma, header=false]{%
  B,54,30,11,4.6,0.4
  A,9.3,20.8,17.8,30.5,21.6
}{\datatable}
  \begin{tikzpicture}
    \begin{axis}[%
      xbar stacked,%
      x post scale=1.3,%
      ytick=data,%
      nodes near coords,% 
      ]
      \addplot+ table [x=1, y expr=\coordindex]
      {\datatable}; 
      \addplot+ table [x=2, y expr=\coordindex]
      {\datatable}; 
      \addplot+ table [x=3, y expr=\coordindex]
      {\datatable}; 
      \addplot+ table [x=4, y expr=\coordindex]
      {\datatable}; 
      \addplot+ table [x=5, y expr=\coordindex]
      {\datatable}; 
    \end{axis}
\end{tikzpicture}
\end{document}

Result:

enter image description here

I found a way to shift all nodes of column 5:

    \documentclass[convert]{standalone}
\usepackage{pgfplots,pgfplotstable}

\pgfplotsset{%
  ,xmin=0%
  ,/tikz/font=\footnotesize%
  ,compat=1.11%
}
\begin{document}

\pgfplotstableread[col sep=comma, header=false]{%
  B,54,30,11,4.6,0.4
  A,9.3,20.8,17.8,30.5,21.6
}{\datatable}
  \begin{tikzpicture}
    \begin{axis}[%
      xbar stacked,%
      x post scale=1.3,%
      ytick=data,%
      ]
      \addplot+[nodes near coords] table [x=1, y expr=\coordindex]
      {\datatable}; 
      \addplot+[nodes near coords] table [x=2, y expr=\coordindex]
      {\datatable}; 
      \addplot+[nodes near coords] table [x=3, y expr=\coordindex]
      {\datatable}; 
      \addplot+[nodes near coords] table [x=4, y expr=\coordindex]
      {\datatable}; 
      \addplot+[%
      nodes near coords={%
        \hspace{.5cm}\pgfmathprintnumber\pgfplotspointmeta%
      },%
      every node near coord/.append style=black%
      ] table [x=5, y expr=\coordindex]
      {\datatable}; 
    \end{axis}
\end{tikzpicture}
\end{document}

Result:

enter image description here

But I only want to shift those nodes that overlap other nodes. Column 5 in row 1 should not be shifted. Any ideas? Ideally, the solution can be applied to all of my stacked bar plots since there are many with overlapping nodes. I'm looking for something like node near coord in row x. A higher value in x post scale does not work in this example since the plot would exceed \linewidth.

4

Here I present a solution that shifts up or down all nodes near coords that are below a given threshold, i.e. regardless of where they are. That minimizes a bit the risk that two or more nodes of small bars overlap each other.

Please have a look at the comments in the code for more details.

% used PGFPlots v1.15
\documentclass[border=5pt]{standalone}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
    \pgfplotsset{
        % use this `compat` level or higher to place `nodes near coords`
        % in the middle of the bars and show only the increment value
        compat=1.9,
        xmin=0,
        /tikz/font=\footnotesize,
    }
\begin{document}
    \pgfplotstableread[col sep=comma, header=false]{
        B,54,30,11,4.6,0.4
        A,9.3,20.8,17.8,30.5,21.6
    }{\datatable}
    \begin{tikzpicture}
        \begin{axis}[
            % reduce the `height' of the plot ...
            height=65pt,
            % ... but avoid changing the default `width' which is scaled from
            % that width ...
            width=\axisdefaultwidth,
            x post scale=1.3,
            % ... and only scale the axis
            scale only axis,
            % enlarge the y limits so there is enough space above it to
            % place there a possible `node near coord'
            enlarge y limits={abs=0.7},
            xbar stacked,
            ytick=data,
            % show `nodes near coords' but adapt the style so that values
            % below a threshold are shifted upwards by the given amount
            nodes near coords,
            % (check here for the value and store the shift value in `\myshift')
            visualization depends on={
                ifthenelse(meta>5,0pt,(-1)^\plotnum * 10pt) \as \myshift
            },
%            % -----------------------------------------------------------------
%            % ~~~ simple solution where was no need for changing node styles
%            % (apply that `\myshift' here in the `nodes near coords style')
%            nodes near coords style={
%                yshift=(\myshift),
%            },
            % -----------------------------------------------------------------
             % ~~~ advanced solution where different node styles are needed
            % nodes that should be moved up/down
            % (adapted from <http://tex.stackexchange.com/a/141006/95441>)
            % #1: the THRESHOLD after which we switch to a special display.
            nodes near coords moved up/.style={
                % define the style of the nodes with "small" values
                small value/.style={
                    text=black,
                    yshift=\myshift,
                },
                % define the style of the nodes with "large" values
                large value/.style={
                    % I choose red here because white didn't look that good
                    text=red,
                },
                every node near coord/.style={
                    check for zero/.code={
                        \pgfmathfloatifflags{\pgfplotspointmeta}{0}{
                            % If meta=0, make the node a coordinate
                            % (which doesn't have text)
                            \pgfkeys{/tikz/coordinate}
                        }{
                            \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}
                            \else
                                % ok, proceed as usual.
                                \pgfkeysalso{/pgfplots/large value}
                            \fi
                        }
                    },
                    check for zero,
                },
            },
            % assign a value to the new style which is the threshold at which
            % the two style `small value' or `large value' are used
            nodes near coords moved up=5,
            % -----------------------------------------------------------------
        ]
            \addplot table [x index=1, y expr=\coordindex] {\datatable};
            \addplot table [x index=2, y expr=\coordindex] {\datatable};
            \addplot table [x index=3, y expr=\coordindex] {\datatable};
            \addplot table [x index=4, y expr=\coordindex] {\datatable};
            \addplot table [x index=5, y expr=\coordindex] {\datatable};
        \end{axis}
    \end{tikzpicture}
\end{document}

image showing the result of above code

  • Nice solution, thank you! Unfortunately it doesn't compile with lualatex 0.95.0: ! Undefined control sequence. \sa@placebox ->\newpage \global \pdfpagewidth. – typokurz Jan 20 '17 at 11:44
  • 1
    Really? Could you try adding \RequirePackage{luatex85} before \documentclass ... – Stefan Pinnow Jan 20 '17 at 11:59
  • Now, it compiles with lualatex. I'm just reading further threads to understand what's wrong without \RequirePackage{luatex85}. – typokurz Jan 20 '17 at 12:01
  • Sorry, I was too fast. The "Really?" should have been an "Of course.". I am also no expert on this but only know that this solved the problem ... (I had another error in mind when you try loading tikz before pgfplots ...) – Stefan Pinnow Jan 20 '17 at 12:06
  • Back in office, a different problem occurs with this solution: I need to use white color for nodes near coords because of the CD colors for the bars. How can I can use black color only for the shifted nodes? – typokurz Jan 24 '17 at 11:37

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.