2

I have a pgfplot that reads from two files. I want a bar chart where the values (bars) of one file appear over one xlabel and the values from another file over another (A and B in this example). My current solution comes fairly close but is 1) a bit hackish as it arranges the entries in the cycle list so the charts are aligned properly and 2) does not align the bars properly with the xticks.

\documentclass[border=5mm]{standalone}
\usepackage{pgfplots}
\usepackage{pgfplotstable}


\pgfplotsset{
    cycle1/.style={green},
    cycle2/.style={orange},
    cycle3/.style={blue},
    cycle4/.style={purple}, 
}

\pgfplotscreateplotcyclelist{mycyclelist}{
    cycle1\\%
    cycle1\\%
    cycle2\\% 
    cycle2\\% 
    cycle3\\%
    cycle3\\%
    cycle4\\%
    cycle4\\%
}

\begin{document}


\pgfplotstableread{
123 11778.83 18995.27 19049.38 22236.73
}\dataA

\pgfplotstableread{
123 1925.39 7014.29 10721.35 24199.01
}\dataB

\begin{tikzpicture}
\begin{axis}[
            ybar=-1pt,
            bar width=5, 
            ymin=0, 
            cycle list name = mycyclelist, 
            xtick={0, 1},
            xticklabels = {
                A, B
            },
            enlarge x limits={abs=0.75}, 
        ]

        \foreach \y in {1, 2, 3, 4} {
            \addplot plot table [x expr=0, col sep=semicolon, header = true, y expr=\thisrowno{\y} / 1000]
                    \dataA;
            \addplot plot table [x expr=1, col sep=semicolon, header = true, y expr=\thisrowno{\y} / 1000]
                    \dataB;
        }
\end{axis}
\end{tikzpicture}

\end{document}

What I am looking for is a solution that aligns the bars properly to the xticks (even better if the cycle-list-trick can be resolved).

The goal would be something like this: goal Whereas in the MWE, the A bars are shifted a bit to the left and the B bars a bit to the right: improperly aligned

  • 1
    What do you mean by "align the charts properly to the xticks"? Do you mean the bars? How exactly do you want to align them? – Jake Jun 5 '14 at 8:27
  • I added a picture of the output the MWE produces: the bars are not in the middle relative to the xticks. (and yes, I meant bars not charts, edited) – mschrimpf Jun 5 '14 at 8:35
2

The shift of a plot depends on the plot index. Use the forget plot option for the plots of \dataA to not increase the plot index for them. Then they will use the same cycle list entry as the following \dataB plot and the shift will be equal for A and B.

enter image description here

\documentclass[border=5mm]{standalone}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
\pgfplotsset{compat=newest}

\pgfplotsset{
    cycle1/.style={green},
    cycle2/.style={orange},
    cycle3/.style={blue},
    cycle4/.style={purple}, 
}

\pgfplotscreateplotcyclelist{mycyclelist}{
  cycle1\\%
  cycle2\\% 
  cycle3\\%
  cycle4\\%
}

\begin{document}

\pgfplotstableread{
123 11778.83 18995.27 19049.38 22236.73
}\dataA

\pgfplotstableread{
123 1925.39 7014.29 10721.35 24199.01
}\dataB

\begin{tikzpicture}
  \begin{axis}[
      ybar=3pt,% should be >0pt
      bar width=6pt, 
      ymin=0, 
      cycle list name = mycyclelist,
      xtick={0,1},
      xticklabels = {A,B},
      enlarge x limits={abs=0.75}, 
    ]

    \foreach \y in {1, 2, 3, 4}{
      \addplot plot table [x expr=0, col sep=semicolon, header = true, y expr=\thisrowno{\y}/1000,
        forget plot% prevents increase of the plot index
        ]\dataA;
      \addplot plot table [x expr=1, col sep=semicolon, header = true, y expr=\thisrowno{\y}/1000]\dataB;}
  \end{axis}
\end{tikzpicture}

\end{document}

It is possible to add a legend. To position it outside of the plot I use

  legend style={legend pos={outer north east}},

as an additional axis option. Then I insert \legend{...} after the foreach loop:

\foreach \y in {1, 2, 3, 4}{
  \addplot plot table [x expr=0, col sep=semicolon, header = true, y expr=\thisrowno{\y}/1000,
    forget plot% prevents increase of the plot index
    ]\dataA;
  \addplot plot table [x expr=1, col sep=semicolon, header = true, y expr=\thisrowno{\y}/1000]\dataB;}
  \legend{green,orange,blue,purple}

enter image description here

Or if you want different entries for A and B:

\foreach \y in {1, 2, 3, 4}{
  \addplot plot table [x expr=0, col sep=semicolon, header = true, y expr=\thisrowno{\y}/1000,
    forget plot% prevents increase of the plot index
    ]\dataA;
  \addplot plot table [x expr=1, col sep=semicolon, header = true, y expr=\thisrowno{\y}/1000]\dataB;
  \addlegendimage{empty legend}% empty legend image
  }
  \legend{A gr,B gr,A or,B or,A bl,B bl,A pu,B pu}

enter image description here


2nd version

You can draw two plots on top of each other:

\documentclass[border=5mm,convert=false]{standalone}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
\pgfplotsset{compat=newest}

\pgfplotsset{
    cycle1/.style={green},
    cycle2/.style={orange},
    cycle3/.style={blue},
    cycle4/.style={purple}, 
}

\pgfplotscreateplotcyclelist{mycyclelist}{
  cycle1\\%
  cycle2\\% 
  cycle3\\%
  cycle4\\%
}

\begin{document}

\pgfplotstableread{
123 11778.83 18995.27 19049.38 22236.73
}\dataA

\pgfplotstableread{
123 1925.39 7014.29 10721.35 24199.01
}\dataB

\begin{tikzpicture}
  \pgfplotsset{%
    every axis/.style={
      ybar=3pt,
      bar width=6pt,
      cycle list name=mycyclelist,
      ymin=0,ymax=25,
      xmin=0,xmax=1,
      enlarge x limits={abs=0.75},
      enlarge y limits={upper=0.1},
    }
  }
  \begin{axis}[
      xtick={0,1},
      xticklabels = {A,B},
      legend style={legend pos=north west}
    ]
    \addlegendimage{empty legend}
    \foreach \y in {1,...,4}{
      \addplot plot table [x expr=0, col sep=semicolon, header = true, y expr=\thisrowno{\y}/1000]\dataA;}
    \legend{A,gr,or,bl,pu}
  \end{axis}
  \begin{axis}[
      axis lines=none,
      ytick=\empty,
      xtick=\empty,
    ]
    \addlegendimage{empty legend}
    \foreach \y in {1,...,4}{
      \addplot plot table [x expr=1, col sep=semicolon, header = true, y expr=\thisrowno{\y}/1000]\dataB;}
    \legend{B,gr,or,bl,pu}
  \end{axis}
\end{tikzpicture}

\end{document}

enter image description here

  • This works perfectly for the MWE, thank you. However, when I add the legend entries options (e.g. legend entries={A, B}), I get the error Missing } inserted. Is there a workaround or even a different solution for this since forget plot sounds unlikely to work with legend entries? – mschrimpf Jun 5 '14 at 14:30
  • 1
    I don't know which kind of legend you need. But I have added to legend examples and a different suggestion without forget plot. – esdd Jun 5 '14 at 23:14
  • Wonderful, thank you so much again. My mistake was that I added forget plot to A and B instead of only A. – mschrimpf Jun 6 '14 at 1:19

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.