2

I want to plot data for a node that has several inflows and one outflow, using stacked histograms. I want the plot to look like this:

This is what I want

First, I have tried stacked histograms (ybar stacked, see the code below), where I draw the negative series first and then add it to the first series. Unfortunately, it does work, even if it works with lines and area style:

Then I tried using separate axis environment for positive and negative values, as suggested in this answer. The problem is that the stacked histogram breaks down once I change ymin - is this a bug?

this works this does not

My question is: is there some way to make this work, other than the hack I used to create the first figure? (There, I am stacking the columns manually - OK for two inflows, but very impractical for five or more - though I guess it could be scripted..)

PS: I realized that the figure has to work also black-and-white, so I need to use patterns. This made my manual stacking impossible, since the patterns have transparent backgrounds - until I found this answer which showed how to combine patterns and fill, so I could get this:

enter image description here

Here is the full code for all the figures:

\documentclass{article}
\usepackage{tikz,pgfplots,pgfplotstable}
\usetikzlibrary{patterns}
\pagestyle{empty}

\begin{document}

\pgfplotstableread{
t   in1 in2 out
1   5   2   7
2   3   0   6
3   1   2   5
4   0   4   4
5   1   6   5
6   4   4   6
7   6   2   7
}\flowData

\begin{tikzpicture}
    \begin{axis}[small,title=This is what I want,ybar,bar shift=0pt,]
        \addplot table[x=t,y expr={-\thisrow{out}}] {\flowData};
        \addplot table[x=t,y expr={\thisrow{in1}+\thisrow{in2}}] {\flowData};
        \addplot table[x=t,y expr={\thisrow{in2}}] {\flowData};
    \end{axis}
\end{tikzpicture}
\ 
\begin{tikzpicture}
    \begin{axis}[small,title=First attempt using ybar stacked,ybar stacked]
        \addplot table[x=t,y expr={-\thisrow{out}}] {\flowData};
        \addplot table[x=t,y expr={\thisrow{out}+\thisrow{in1}}] {\flowData};
        \addplot table[x=t,y=in2] {\flowData};
    \end{axis}
\end{tikzpicture}

\begin{tikzpicture}
    \begin{axis}[small,title=Check: using lines is OK,stack plots=y]
        \addplot table[x=t,y expr={-\thisrow{out}}] {\flowData};
        \addplot table[x=t,y expr={\thisrow{out}+\thisrow{in1}}] {\flowData};
        \addplot table[x=t,y=in2] {\flowData};
    \end{axis}
\end{tikzpicture}
\ 
\begin{tikzpicture}
    \begin{axis}[small,title=Check: using area style is OK,stack plots=y,area style]
        \addplot table[x=t,y expr={-\thisrow{out}}] {\flowData} \closedcycle;
        \addplot table[x=t,y expr={\thisrow{out}+\thisrow{in1}}] {\flowData} \closedcycle;
        \addplot table[x=t,y=in2] {\flowData} \closedcycle;
    \end{axis}
\end{tikzpicture}

\begin{tikzpicture}
    \begin{axis}[small,title=Test: only inflows,ybar stacked]
        \pgfplotsset{cycle list shift=1}
        \addplot table[x=t,y=in1] {\flowData};
        \addplot table[x=t,y=in2] {\flowData};
    \end{axis}
\end{tikzpicture}
\
\begin{tikzpicture}
    \begin{axis}[small,title={Test: only inflows with ymin=-8},ybar stacked,ymin=-8]
        \pgfplotsset{cycle list shift=1}
        \addplot table[x=t,y=in1] {\flowData};
        \addplot table[x=t,y=in2] {\flowData};
    \end{axis}
\end{tikzpicture}

\pgfplotsset{ % redefine the cycle list used for bar- and area plots
    /pgfplots/bar cycle list/.style={/pgfplots/cycle list={%
        {blue!80!black,fill=white,postaction={pattern=north east lines,pattern color=blue!75!white}},%
        {green!75!black,fill=white,postaction={pattern=crosshatch dots,pattern color=green!90!white}},%
        {red!80!black,fill=white,postaction={pattern=crosshatch,pattern color=red!67!white}}}
    }
}
\begin{tikzpicture}
    \begin{axis}[small,title={This is what I \emph{really} want},ybar,bar shift=0pt,]
        \addplot table[x=t,y expr={-\thisrow{out}}] {\flowData};
        \addplot table[x=t,y expr={\thisrow{in1}+\thisrow{in2}}] {\flowData};
        \addplot table[x=t,y expr={\thisrow{in2}}] {\flowData};
    \end{axis}
\end{tikzpicture}

\end{document}
2

When I understood your question right, than the following code does "what you really want", right? Since PGFPlots v1.13 this can be done quite easily with the new feature stack negative=separate.

\documentclass[border=5pt]{standalone}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
    \usetikzlibrary{patterns}
    \pgfplotsset{ % redefine the cycle list used for bar- and area plots
        /pgfplots/bar cycle list/.style={
            /pgfplots/cycle list={
                    blue!80!black,
                    fill=white,
                    postaction={
                        pattern=north east lines,
                        pattern color=blue!75!white,
                    }
                \\
                    green!75!black,
                    fill=white,
                    postaction={
                        pattern=crosshatch dots,
                        pattern color=green!90!white,
                    }
                \\
                    red!80!black,
                    fill=white,
                    postaction={
                        pattern=crosshatch,
                        pattern color=red!67!white,
                    }
                \\
            },
        },
    }
\begin{document}
    \begin{tikzpicture}
            \pgfplotstableread{
                t   in1 in2 out
                1   5   2   7
                2   3   0   6
                3   1   2   5
                4   0   4   4
                5   1   6   5
                6   4   4   6
                7   6   2   7
            }\flowData
        \begin{axis}[
            small,
            ybar stacked,
            % use new feature from PGFPlots v1.13
            stack negative=separate,
        ]
            \addplot table [x=t,y expr={-\thisrow{out}}] {\flowData};
            % to produce your *really* wanted output, I had to reverse the
            % order of the `in' streams
            \addplot table [x=t,y=in2] {\flowData};
            \addplot table [x=t,y=in1] {\flowData};
        \end{axis}
    \end{tikzpicture}
\end{document}

image showing the result of above code

  • You are welcome. If you don't have already: Besides accepting the answer you could in addition upvote the answer by clicking on the up-arrow above the number on the left side of the answer. – Stefan Pinnow Dec 8 '16 at 15:02

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.