# [Tex/LaTex] pgfplots, xbar stacked: Prevent overlapping by shifting only one node

bar chartnodesnodes-near-coordspgfplots

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}
`