1

I am trying to reuse a stacked bar plot I created a few months ago that looked like this:

enter image description here

The source code I'm pretty sure I used to create is was:

\documentclass{article}

\usepackage{pgfplots,tikz}

\begin{document}
    \begin{tikzpicture}
        \begin{axis}[
                xbar stacked,
                legend style={
                legend columns=4,
                    at={(xticklabel cs:0.5)},
                    anchor=north,
                    draw=none
                },
                ytick=data,
                axis y line*=none,
                axis x line*=bottom,
                tick label style={font=\footnotesize},
                legend style={font=\footnotesize},
                label style={font=\footnotesize},
                xtick={-100,-75,-50,-25,0,25,50,75,100},
                width=.9\textwidth,
                bar width=6mm,
                xlabel={\%},
                yticklabels={A, B, C},
                xmin=-100,
                xmax=100,
                area legend,
                y=8mm,
                enlarge y limits={abs=0.625},
                restrict x to domain*=:0,
            ]
            \addplot[yellow,fill=yellow] coordinates
            {(-8,2) (-17,1) (-7,0)};
            \addplot[red,fill=red] coordinates
            {(-8,2) (0,1) (-7,0)};
            \addplot[green,fill=green] coordinates
            {(0,2) (43,1) (40,0)};
            \addplot[blue,fill=blue] coordinates
            {(83,2) (39,1) (47,0)};
        \end{axis}  
        \begin{axis}[
                xbar stacked,
                legend style={
                legend columns=4,
                    at={(xticklabel cs:0.5)},
                    anchor=north,
                    draw=none
                },
                ytick=data,
                axis y line*=none,
                axis x line*=bottom,
                tick label style={font=\footnotesize},
                legend style={font=\footnotesize},
                label style={font=\footnotesize},
                xtick={-100,-75,-50,-25,0,25,50,75,100},
                width=.9\textwidth,
                bar width=6mm,
                xlabel={\%},
                yticklabels={A, B, C},
                xmin=-100,
                xmax=100,
                area legend,
                y=8mm,
                enlarge y limits={abs=0.625},
                restrict x to domain*=0:,
            ]
            \addplot[red,fill=red] coordinates
            {(-8,2) (0,1) (-7,0)};
            \addplot[yellow,fill=yellow] coordinates
            {(-8,2) (-17,1) (-7,0)};
            \addplot[green,fill=green] coordinates
            {(0,2) (43,1) (40,0)};
            \addplot[blue,fill=blue] coordinates
            {(83,2) (39,1) (47,0)};
            \legend{strongly disagree, disagree, agree, strongly agree}
        \end{axis}  
    \end{tikzpicture}
\end{document}

I remember spending hours playing around with different things, especially trying to figure how to make sure my plots were not overlaid one above the other and the legend appeared in the proper order, which is when I figured that I had to create two different x axes and make sure I readded all four plots in the axis that lays out the legend even though not all four are drawn at this time.

I have tried compiling that very same code on a different computer, and presumably a different version of LaTeX and all the modules (my computer at the time, which I don't have access to anymore, used Debian stable, so slightly outdated packages, and now I'm using TeXworks on Windows). And I get a different result:

enter image description here

As you can see, the yellow bars are not shown (I suppose they are hidden under the red bars even though they are drawn later), and even the red bars don't quote end where they're supposed to. I've looked over the whole code and, while I must admit I've never fully understood it even in the first place, I'm totally unable to figure what's wrong with it.

Can anyone help?

  • Note that the red bars are all starting at -25. I don't know where this comes from at all. The yellow ones are being drawn in the same way, also starting at -25, but before the red ones, so are covered up. I think you need to handle these negative bars in a different way. – Andrew Swann Mar 13 '15 at 13:17
2

The negative bars are being plotted starting at the tick mark -25 instead of 0; this is most clear if you remove your second axis command. This applies to both the yellow and the red bars and one covers the other. I don't why this is happening but it seems this can be fixed by adding a zero row of dummy coordinates to the plot producing the negative bars:

  \addplot coordinates {(0,2) (0,1) (0,0)};

Sample output

Below I give this alteration to your original code, followed by a shorter version where the common options are pulled out in to the options of the tikzpicture rather than having to be repeated for each axis.

\documentclass{article}

\usepackage{pgfplots,tikz}
\pgfplotsset{compat=1.12}

\begin{document}
    \begin{tikzpicture}
      \begin{axis}[
          xbar stacked,
                legend style={
                legend columns=4,
                    at={(xticklabel cs:0.5)},
                    anchor=north,
                    draw=none
                },
                ytick=data,
                axis y line*=none,
                axis x line*=bottom,
                tick label style={font=\footnotesize},
                legend style={font=\footnotesize},
                label style={font=\footnotesize},
                xtick={-100,-75,-50,-25,0,25,50,75,100},
                width=.9\textwidth,
                bar width=6mm,
                xlabel={\%},
                yticklabels={A, B, C},
                xmin=-100,
                xmax=100,
                area legend,
                y=8mm,
                enlarge y limits={abs=0.625},
                restrict x to domain*=:0,
            ]
            \addplot coordinates {(0,2) (0,1) (0,0)};
            \addplot[yellow,fill=yellow] coordinates
            {(-8,2) (-17,1) (-7,0)};
            \addplot[red,fill=red] coordinates
            {(-8,2) (0,1) (-7,0)};
            \addplot[green,fill=green] coordinates
            {(0,2) (43,1) (40,0)};
            \addplot[blue,fill=blue] coordinates
            {(83,2) (39,1) (47,0)};
        \end{axis}  
        \begin{axis}[
                xbar stacked,
                legend style={
                legend columns=4,
                    at={(xticklabel cs:0.5)},
                    anchor=north,
                    draw=none
                },
                ytick=data,
                axis y line*=none,
                axis x line*=bottom,
                tick label style={font=\footnotesize},
                legend style={font=\footnotesize},
                label style={font=\footnotesize},
                xtick={-100,-75,-50,-25,0,25,50,75,100},
                width=.9\textwidth,
                bar width=6mm,
                xlabel={\%},
                yticklabels={A, B, C},
                xmin=-100,
                xmax=100,
                area legend,
                y=8mm,
                enlarge y limits={abs=0.625},
                restrict x to domain*=0:,
            ]
            \addplot[red,fill=red] coordinates
            {(-8,2) (0,1) (-7,0)};
            \addplot[yellow,fill=yellow] coordinates
            {(-8,2) (-17,1) (-7,0)};
            \addplot[green,fill=green] coordinates
            {(0,2) (43,1) (40,0)};
            \addplot[blue,fill=blue] coordinates
            {(83,2) (39,1) (47,0)};
            \legend{strongly disagree, disagree, agree, strongly agree}
        \end{axis}  
    \end{tikzpicture}
\end{document}

Shorter coding:

\documentclass{article}

\usepackage{pgfplots,tikz}
\pgfplotsset{compat=1.12}

\begin{document}
    \begin{tikzpicture}[/pgfplots,
      xbar stacked,
      legend style={
        legend columns=4,
        at={(xticklabel cs:0.5)},
        anchor=north,
        draw=none
        },
        ytick=data,
        axis y line*=none,
        axis x line*=bottom,
        tick label style={font=\footnotesize},
        legend style={font=\footnotesize},
        label style={font=\footnotesize},
        xtick={-100,-75,-50,-25,0,25,50,75,100},
        width=.9\textwidth,
        /pgf/bar width=6mm,
        xlabel={\%},
        yticklabels={A, B, C},
        xmin=-100,
        xmax=100,
        area legend,
        y=8mm,
        enlarge y limits={abs=0.625}]
      \begin{axis}[restrict x to domain*=:0]
            \addplot coordinates {(0,2) (0,1) (0,0)};
            \addplot[yellow,fill=yellow] coordinates
            {(-8,2) (-17,1) (-7,0)};
            \addplot[red,fill=red] coordinates
            {(-8,2) (0,1) (-7,0)};
            \addplot[green,fill=green] coordinates
            {(0,2) (43,1) (40,0)};
            \addplot[blue,fill=blue] coordinates
            {(83,2) (39,1) (47,0)};
        \end{axis}  
        \begin{axis}[restrict x to domain*=0:]
            \addplot[red,fill=red] coordinates
            {(-8,2) (0,1) (-7,0)};
            \addplot[yellow,fill=yellow] coordinates
            {(-8,2) (-17,1) (-7,0)};
            \addplot[green,fill=green] coordinates
            {(0,2) (43,1) (40,0)};
            \addplot[blue,fill=blue] coordinates
            {(83,2) (39,1) (47,0)};
            \legend{strongly disagree, disagree, agree, strongly agree}
        \end{axis}  
    \end{tikzpicture}
\end{document}
  • 1
    Thank you so much! Pgfplots is the most complicated package I have ever have to use, I wonder if a day will come when I will be able really to understand how it works. I have noticed your solution doesn't work anymore if one removes the compat=1.12. Do you have an idea why? – scozy Mar 13 '15 at 13:42
  • 1
    Adding a compat option should give consistency in compiling as pgfplots gets updated. I don't what has changed between versions, but as you say the version makes a difference. – Andrew Swann Mar 13 '15 at 13:47
1

In PGFPlots v1.13 there was introduced a new feature that does exactly what you want without having to plot everything twice ...

You just need to use this compat level or higher or state stack negative=separate to the axis options.

% used PGFPlots v1.14
\documentclass[border=5pt]{standalone}
\usepackage{pgfplots}
    \pgfplotsset{
        % using this `compat' level or higher changes the value of `stack negative'
        % from `on previous' to `separate' which is exactly what you want
        compat=1.13,
    }
\begin{document}
    \begin{tikzpicture}
        \begin{axis}[
            footnotesize,
            width=.9\textwidth,
            height=.35\textwidth,
            axis y line*=left,
            axis x line*=bottom,
            xmin=-25,
            xmax=100,
            ytick=data,
            yticklabels={A, B, C},
            xtick distance=25,
            enlarge y limits={abs=0.625},
            xlabel={\%},
            legend style={
                legend columns=4,
                at={(xticklabel cs:0.5)},
                anchor=north,
                draw=none,
            },
            xbar stacked,
            bar width=6mm,
            area legend,
            % just added these to show that this is the desired result
            nodes near coords,
            nodes near coords style={
                color=black,
                font=\footnotesize,
            },
        ]
            \addplot [yellow,fill=yellow] coordinates
                {(-8,2) (-17,1) (-7,0)};
            \addplot [red,fill=red] coordinates
                {(-8,2) (0,1) (-7,0)};
            \addplot [green,fill=green] coordinates
                {(0,2) (43,1) (40,0)};
            \addplot [blue,fill=blue] coordinates
                {(83,2) (39,1) (47,0)};

            \legend{
                strongly disagree,
                disagree,
                agree,
                strongly agree,
            }
        \end{axis}
    \end{tikzpicture}
\end{document}

image showing the result of above code

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.