4

I would like my ybars to be stacked the same way positively than negatively. It works for positive values but not for negative ones. On the given example, ThirdCol should be stacked negatively. Any idea to stack it ?

\documentclass[border=5mm]{standalone}

\usepackage{pgfplots}

\pgfplotstableread{
Year    OneCol  SecCol  ThirdCol ForthCol
2005    10     50      -10     30  
2006    -40     60      -15     90
2007    -20     60      -15     60
}\datatable


\pgfplotsset{   width=5cm,
        compat=newest,
        height=5cm}
\usepgfplotslibrary{dateplot}

\begin{document}%
    \begin{tikzpicture}
        \begin{axis}[
            x tick label style={/pgf/number format/1000 sep=},
            ybar stacked,
            bar shift=0pt,
            enlarge x limits=0.15,
            bar width=1em,
            ymin=-100,
            legend style={
                at={(0.5,-0.1)},
                anchor=north,
                draw=none }
          ]
\addplot table [y index=1] {\datatable};
  \addplot table [y index=2] {\datatable};
   \addplot table [y index=3] {\datatable};
   \addplot table [y index=4] {\datatable};
  \legend{Factor1,Factor2,Factor3,Factor4}
  \end{axis}
\end{tikzpicture}

\end{document}

enter image description here

  • 1
    So you want the negative bars to be stacked on top of each other downward from the zero axis? It would take a bit of work to achieve that, and it would be somewhat confusing because the order of the bars would change. Maybe take a look at waterfall charts? – Jake Apr 21 '13 at 14:47
  • Well i already tried with waterfall charts, but the problem is i cannot use "bar shift=0pt" option. – gVermandel Apr 21 '13 at 15:27
3

In PGFPlots v1.13 your example now works with the new key stack negative=separate, where `separate' is the default value. Find the full code below, which I just reordered a bit. It was also added a similar example to the manual in the section 4.5.9 on page 99.

Please note: For some reason compat=newest doesn't seem to work, but compat=1.13 does.

\documentclass[border=5mm]{standalone}
\usepackage{pgfplots}
    \usepgfplotslibrary{dateplot}
    \pgfplotsset{
%        compat=newest,  % <-- does not work; don't know why
        compat=1.13,     % <-- works as expected
        width=5cm,
        height=5cm,
    }
\begin{document}
    \begin{tikzpicture}
        \pgfplotstableread{
            Year    OneCol  SecCol  ThirdCol ForthCol
            2005    10     50      -10     30
            2006    -40     60      -15     90
            2007    -20     60      -15     60
        }\datatable
        \begin{axis}[
            x tick label style={
                /pgf/number format/1000 sep=,
            },
            ybar stacked,
            bar shift=0pt,
            enlarge x limits=0.15,
            bar width=1em,
            ymin=-100,
            legend style={
                at={(0.5,-0.1)},
                anchor=north,
                draw=none,
            },
        ]
            \addplot table [y index=1] {\datatable};
            \addplot table [y index=2] {\datatable};
            \addplot table [y index=3] {\datatable};
            \addplot table [y index=4] {\datatable};
            \legend{Factor1,Factor2,Factor3,Factor4}
        \end{axis}
    \end{tikzpicture}
\end{document}

image to the above code

  • Regarding "compat=newest does not have the same effect as compat=1.13": that is indeed a software issue. I will address it in the next version of pgfplots. – Christian Feuersänger Jan 10 '16 at 21:35
4

Instead of restructuring your input data, you can also do this automatically via PGFPlots restrict y to domain* feature. Your example would then be plotted by the following source code:

\documentclass[border=5mm]{standalone}

\usepackage{pgfplots}

\pgfplotstableread{
Year    OneCol  SecCol  ThirdCol ForthCol
2005    10     50      -10     30  
2006    -40     60      -15     90
2007    -20     60      -15     60
}\datatable

\pgfplotsset{   width=5cm,
compat=newest,
height=5cm}
\usepgfplotslibrary{dateplot}

\begin{document}%
  \begin{tikzpicture}
    \begin{axis}[
      x tick label style={/pgf/number format/1000 sep=},
      ybar stacked,
      bar width=1em,
      ymin=-100,
      ymax=200,
      legend style={
      at={(0.5,-0.1)},
      anchor=north,
      draw=none },
      restrict y to domain*=:0, % negative values
      y=1pt,  % important workaround!
      ]
      \addplot table [y index=1] {\datatable};
      \addplot table [y index=2] {\datatable};
      \addplot table [y index=3] {\datatable};
      \addplot table [y index=4] {\datatable};
      \legend{Factor1,Factor2,Factor3,Factor4}
    \end{axis}
    \begin{axis}[
      x tick label style={/pgf/number format/1000 sep=},
      ybar stacked,
      bar width=1em,
      ymin=-100,
      ymax=200,
      legend style={
      at={(0.5,-0.1)},
      anchor=north,
      draw=none },
      restrict y to domain*=0:, % positive values
      y=1pt,  % important workaround!
      ]
      \addplot table [y index=1] {\datatable};
      \addplot table [y index=2] {\datatable};
      \addplot table [y index=3] {\datatable};
      \addplot table [y index=4] {\datatable};
      \legend{Factor1,Factor2,Factor3,Factor4}
    \end{axis}
  \end{tikzpicture}

\end{document}

This would result in the following graph: Resulting graph

2

Ok i've done it but it's a really botch work, if someone has a better way to code it, i'd grateful.

I had to separate positive value from negative and store them in 2 different columns and then plot them by declaring 2 axis, one axis for positive values, another for negative values.

    \documentclass{standalone}
\usepackage{pgfplots,filecontents}
\usepgfplotslibrary{units}
\pgfplotsset{width=16cm,compat=newest}

\begin{filecontents}{total.dos}
Yr  C1  C2      C3      C4  C5      C6  C7  C8      C9  C10
2003    0   -0.11864    0.087399    0   0.012936    0   0   -0.097901   0   -0.090281   
2004    0   -0.73465    0.56238 0   0.044703    0   0   -0.04678    0.051024    0   
2005    0.5 0       0.64271 0   0.071566    0   0   -0.25326    0.026343    0   
2006    0   -0.9268 0.74394 0   0.10508 0   0   -0.26348    0.058272    0   

\end{filecontents}

\begin{document}
\begin{tikzpicture}
\begin{axis}[const plot,
  stack plots=y,
  xlabel={Energy},
  x unit={eV},
  ylabel={Intensity},
  no markers,
  ymin=-3,
  ymax=3
]
  \addplot [fill=red,draw=none] table [x index=0,y index=3] {total.dos}\closedcycle;
  \addplot [fill=blue,draw=none,fill opacity=0.25] table [x index=0,y index=1] {total.dos}\closedcycle;
  \addplot [fill=green,draw=none,fill opacity=0.25] table [x index=0,y index=5] {total.dos}\closedcycle;
 \addplot [fill=yellow,draw=none,fill opacity=0.5] table [x index=0,y index=7] {total.dos}\closedcycle;
\end{axis}
\begin{axis}[const plot,
  stack plots=y,
  no markers,
  ymin=-3,
  ymax=3,
  xtick=\empty,
  ytick=\empty,
  axis x line=none,
  axis y line=none
]
  \addplot [fill=red,draw=none] table [x index=0, y index=4] {total.dos}\closedcycle;
  \addplot [fill=blue,draw=none,fill opacity=0.25] table [x index=0,y index=2] {total.dos}\closedcycle;
 \addplot [fill=green,draw=none,fill opacity=0.25] table [x index=0,y index=6] {total.dos}\closedcycle;
\addplot [fill=yellow,draw=none,fill opacity=0.5] table [x index=0,y index=8] {total.dos}\closedcycle;
\end{axis}
\end{tikzpicture}
\end{document}

enter image description here

1

A far simpler solution would be to split the domains and offset the abscissa by a tiny amount.

\pgfplotstableread{
Year       OneCol  SecCol  ThirdCol ForthCol
2005           10      50         0       30  
2005.0001       0       0       -10        0  
2006            0      60         0       90
2006.0001     -40       0       -15        0
2007            0      60         0       60
2007.0001     -20       0       -15        0
}\datatable

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.