# pgfplots, xbar stacked: Prevent overlapping by shifting only one node

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}

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,%
]
{\datatable};
{\datatable};
{\datatable};
{\datatable};
{\datatable};
\end{axis}
\end{tikzpicture}
\end{document}


Result:

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}

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};
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:

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.

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}
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
% #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}


• 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
• 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