[Tex/LaTex] pgfplots: group stacked bars

pgfplotstikz-pgf

I'm trying to create groups of 5 stacked xbars, using y expr={\thisrow{y} - (mod(\thisrow{y},5)/2)}. However, after some groups, the calculation seems to get thrown off and the third group actually consists of 6 bars:

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=1.9}
\usepackage{pgfplotstable}
\begin{document}
\pgfplotstableread{%
x y
0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 10
11 11
12 12
13 13
14 14
15 15
16 16
17 17
18 18
19 19
20 20
21 21
}\loadedtable

    \begin{figure}[h]
        \begin{tikzpicture}
            \begin{axis}[xbar stacked, ytick=data, y=0.9cm]
                \addplot table[x=x,y expr={\thisrow{y} - (mod(\thisrow{y},5)/2)}] \loadedtable ;
                \addplot table[x=x,y expr={\thisrow{y} - (mod(\thisrow{y},5)/2)}] \loadedtable ;
            \end{axis}
        \end{tikzpicture}
    \end{figure}
\end{document}

enter image description here

Best Answer

This happens because of numerical inaccuracies of the mod function when using the fpu library (which is the case for most calculations within an axis environment). Sometimes, the function incorrectly returns the divisor instead of zero (\pgfmathparse{mod(15,5)}, for instance).

You can fix this by defining a new version of the mod function that checks for this error:

\pgfmathdeclarefunction{fpumod}{2}{%
    \pgfmathfloatdivide{#1}{#2}%
    \pgfmathfloatint{\pgfmathresult}%
    \pgfmathfloatmultiply{\pgfmathresult}{#2}%
    \pgfmathfloatsubtract{#1}{\pgfmathresult}%
    \pgfmathfloatifapproxequalrel{\pgfmathresult}{#2}{\def\pgfmathresult{0}}{}%
}

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=1.9}
\usepackage{pgfplotstable}

\pgfmathdeclarefunction{fpumod}{2}{%
    \pgfmathfloatdivide{#1}{#2}%
    \pgfmathfloatint{\pgfmathresult}%
    \pgfmathfloatmultiply{\pgfmathresult}{#2}%
    \pgfmathfloatsubtract{#1}{\pgfmathresult}%
    \pgfmathfloatifapproxequalrel{\pgfmathresult}{#2}{\def\pgfmathresult{0}}{}%
}

\begin{document}
\pgfplotstableread{%
x y
0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 10
11 11
12 12
13 13
14 14
15 15
16 16
17 17
18 18
19 19
20 20
21 21
}\loadedtable

        \begin{tikzpicture}
            \begin{axis}[xbar stacked, ytick=data, y=0.9cm]
                \addplot table[x=x,y expr={\thisrow{y} - (fpumod(\thisrow{y},5)/2)}] \loadedtable ;
                \addplot table[x=x,y expr={\thisrow{y} - (fpumod(\thisrow{y},5)/2)}] \loadedtable ;
            \end{axis}
        \end{tikzpicture}
\end{document}