8

Is there a way to group pie charts using groupplots? I want to have something similar to this: enter image description here

Here is the MWE:

\documentclass[times]{article}
\usepackage{pgfplots, pgfplotstable}
\usepackage{tikz}
\usepgfplotslibrary{groupplots}
\begin{document}
\newcommand{\legend}[2][]{
 \begin{scope}[#1]
 \path
    \foreach \n/\s in {#2}
        {
              ++(0,-10pt) node[\s,legend box] {} +(5pt,0) node[legend label] {\n}
        }
;
\end{scope}
}
\tikzstyle{chart}=[
legend label/.style={font={\scriptsize},anchor=west,align=left},
legend box/.style={rectangle, draw, minimum size=5pt},
axis/.style={black,semithick,->},
axis label/.style={anchor=east,font={\tiny}},
]
\tikzstyle{pie chart}=[
chart,
slice/.style={line cap=round, line join=round, very thick,draw=white},
pie title/.style={font={\bf}},
slice type/.style 2 args={
    ##1/.style={fill=##2},
    values of ##1/.style={}
}
]
\pgfdeclarelayer{background}
\pgfdeclarelayer{foreground}
\pgfsetlayers{background,main,foreground}
\newcommand{\pie}[3][]{
\begin{scope}[#1]
\pgfmathsetmacro{\curA}{90}
\pgfmathsetmacro{\r}{1}
\def\c{(0,0)}
\node[pie title] at (90:1.3) {#2};
\foreach \v/\s in{#3}{
    \pgfmathsetmacro{\deltaA}{\v/100*360}
    \pgfmathsetmacro{\nextA}{\curA + \deltaA}
    \pgfmathsetmacro{\midA}{(\curA+\nextA)/2}

    \path[slice,\s] \c
        -- +(\curA:\r)
        arc (\curA:\nextA:\r)
        -- cycle;
    \pgfmathsetmacro{\d}{max((\deltaA * -(.4/50) + 1) , .5)}

    \begin{pgfonlayer}{foreground}
    \path \c -- node[pos=\d,pie values,values of \s]{$\v\%$} +(\midA:\r);
    \end{pgfonlayer}

    \global\let\curA\nextA
}
\end{scope}
}
\begin{figure}
\begin{tikzpicture}
[
pie chart,
slice type={inlined}{lightgray},
slice type={noninlined}{darkgray},
pie values/.style={font={\tiny}},
scale=1
]

\pie{\footnotesize{benchmark}}{41/inlined,13/noninlined}

\legend[shift={(-1cm,-1cm)}]{{Inlined}/inlined, {Not inlined}/noninlined}
\end{tikzpicture}
\end{figure}
  \end{document}
  • Does it have to be using groupplots or would another approach be valid? – Gonzalo Medina Feb 22 '14 at 0:24
  • other approach is also fine, I just want to automate the positioning of the plots. I will have 72 pie charts – bekon Feb 22 '14 at 16:03
7

To place the pie charts, you can use \subcaptionbox (from the subcaption package); the code for the pie inclusion can be shortened with the help of a new command \putpie; using two minipages inside a \makebox you can place the legend at the desired location:

\documentclass{article}
\usepackage{pgfplots, pgfplotstable}
\usepackage{subcaption}
\usepgfplotslibrary{groupplots}
\pgfplotsset{compat=newest}

\newcommand{\legend}[2][]{
 \begin{scope}[#1]
 \path
    \foreach \n/\s in {#2}
        {
              ++(0,-10pt) node[\s,legend box] {} +(5pt,0) node[legend label] {\n}
        }
;
\end{scope}
}

\tikzset{
chart/.style={
  legend label/.style={font={\scriptsize},anchor=west,align=left},
  legend box/.style={rectangle, draw, minimum size=5pt},
  axis/.style={black,semithick,->},
  axis label/.style={anchor=east,font={\tiny}},
  },
pie chart/.style={
  chart,
  slice/.style={line cap=round, line join=round, very thick,draw=white},
  pie title/.style={font={\bfseries}},
  slice type/.style 2 args={
    ##1/.style={fill=##2},
    values of ##1/.style={}
    }
  }
}
\pgfdeclarelayer{background}
\pgfdeclarelayer{foreground}
\pgfsetlayers{background,main,foreground}

\newcommand{\pie}[3][]{
\begin{scope}[#1]
\pgfmathsetmacro{\curA}{90}
\pgfmathsetmacro{\r}{1}
\def\c{(0,0)}
\node[pie title] at (90:1.3) {#2};
\foreach \v/\s in{#3}{
    \pgfmathsetmacro{\deltaA}{\v/100*360}
    \pgfmathsetmacro{\nextA}{\curA + \deltaA}
    \pgfmathsetmacro{\midA}{(\curA+\nextA)/2}

    \path[slice,\s] \c
        -- +(\curA:\r)
        arc (\curA:\nextA:\r)
        -- cycle;
    \pgfmathsetmacro{\d}{max((\deltaA * -(.4/50) + 1) , .5)}

    \begin{pgfonlayer}{foreground}
    \path \c -- node[pos=\d,pie values,values of \s]{$\v\%$} +(\midA:\r);
    \end{pgfonlayer}

    \global\let\curA\nextA
}
\end{scope}
}

\newcommand\putpie[1]{%
\subcaptionbox{}{%
  \begin{tikzpicture}
  #1
  \end{tikzpicture}}%
}

\begin{document}

\begin{figure}
\tikzset{every picture/.style={
  pie chart,
  slice type={inlined}{lightgray},
  slice type={noninlined}{darkgray},
  pie values/.style={font={\tiny}},
  scale=1
  }
}
\pgfplotsset{legend style={
  anchor=north,
  legend columns=2,
  cells={anchor=west},
  font=\footnotesize,
  rounded corners=2pt,
  },
}
\captionsetup[subfigure]{labelformat=empty}% to suppress the labels from captions
\makebox[\linewidth][l]{%
\begin{minipage}{\linewidth}
\centering
\putpie{\pie{{\footnotesize benchmark}}{41/inlined,13/noninlined}}\hfill
\putpie{\pie{{\footnotesize benchmark}}{41/inlined,13/noninlined}}\hfill
\putpie{\pie{{\footnotesize benchmark}}{41/inlined,13/noninlined}}\hfill
\putpie{\pie{{\footnotesize benchmark}}{41/inlined,13/noninlined}}\hfill
\putpie{\pie{{\footnotesize benchmark}}{41/inlined,13/noninlined}}\\
\putpie{\pie{{\footnotesize benchmark}}{41/inlined,13/noninlined}}\hfill
\putpie{\pie{{\footnotesize benchmark}}{41/inlined,13/noninlined}}\hfill
\putpie{\pie{{\footnotesize benchmark}}{41/inlined,13/noninlined}}\hfill
\putpie{\pie{{\footnotesize benchmark}}{41/inlined,13/noninlined}}\hfill
\putpie{\pie{{\footnotesize benchmark}}{41/inlined,13/noninlined}}\\
\putpie{\pie{{\footnotesize benchmark}}{41/inlined,13/noninlined}}\hfill
\putpie{\pie{{\footnotesize benchmark}}{41/inlined,13/noninlined}}\hfill
\putpie{\pie{{\footnotesize benchmark}}{41/inlined,13/noninlined}}\hfill
\putpie{\pie{{\footnotesize benchmark}}{41/inlined,13/noninlined}}\hfill
\putpie{\pie{{\footnotesize benchmark}}{41/inlined,13/noninlined}}
\end{minipage}\quad
\begin{minipage}{3cm}
\raggedleft
\begin{tikzpicture}[remember picture]
\legend{{Inlined}/inlined, {Not inlined}/noninlined}
\end{tikzpicture}%
\end{minipage}}
\end{figure}

\end{document}

enter image description here

To get finer control over the vertical alignment for various charts, it's better to use the subfigure environment; also, now the title for the charts is delegated to \putpie using \caption, An extra row of \putpie commands with empty contents can be used to produce a title for each column:

\documentclass{article}
\usepackage{pgfplots, pgfplotstable}
\usepackage{subcaption}
\usepgfplotslibrary{groupplots}
\pgfplotsset{compat=newest}

\newcommand{\legend}[2][]{
 \begin{scope}[#1]
 \path
    \foreach \n/\s in {#2}
        {
              ++(0,-10pt) node[\s,legend box] {} +(5pt,0) node[legend label] {\n}
        }
;
\end{scope}
}

\tikzset{
chart/.style={
  legend label/.style={font={\scriptsize},anchor=west,align=left},
  legend box/.style={rectangle, draw, minimum size=5pt},
  axis/.style={black,semithick,->},
  axis label/.style={anchor=east,font={\tiny}},
  },
pie chart/.style={
  chart,
  slice/.style={line cap=round, line join=round, very thick,draw=white},
  pie title/.style={font={\bfseries}},
  slice type/.style 2 args={
    ##1/.style={fill=##2},
    values of ##1/.style={}
    }
  }
}
\pgfdeclarelayer{background}
\pgfdeclarelayer{foreground}
\pgfsetlayers{background,main,foreground}

\newcommand{\pie}[3][]{
\begin{scope}[#1]
\pgfmathsetmacro{\curA}{90}
\pgfmathsetmacro{\r}{1}
\def\c{(0,0)}
\foreach \v/\s in{#3}{
    \pgfmathsetmacro{\deltaA}{\v/100*360}
    \pgfmathsetmacro{\nextA}{\curA + \deltaA}
    \pgfmathsetmacro{\midA}{(\curA+\nextA)/2}

    \path[slice,\s] \c
        -- +(\curA:\r)
        arc (\curA:\nextA:\r)
        -- cycle;
    \pgfmathsetmacro{\d}{max((\deltaA * -(.4/50) + 1) , .5)}

    \begin{pgfonlayer}{foreground}
    \path \c -- node[pos=\d,pie values,values of \s]{$\v\%$} +(\midA:\r);
    \end{pgfonlayer}

    \global\let\curA\nextA
}
\end{scope}
}

\newlength\PieWd
\setlength\PieWd{2.2cm}
\newcommand\putpie[2]{%
\begin{subfigure}[t]{\PieWd}
  \centering
  \caption{#2}
  \begin{tikzpicture}
  #1
  \end{tikzpicture}%
\end{subfigure}%
}


\begin{document}

\begin{figure}
\tikzset{every picture/.style={
  pie chart,
  slice type={inlined}{lightgray},
  slice type={noninlined}{darkgray},
  pie values/.style={font={\tiny}},
  scale=1
  }
}
\pgfplotsset{legend style={
  anchor=north,
  legend columns=2,
  cells={anchor=west},
  font=\footnotesize,
  rounded corners=2pt,
  },
}
\captionsetup[subfigure]{labelformat=empty,textfont=bf}% to suppress the labels from captions and place the name in bold-face
\makebox[\linewidth][l]{%
\begin{minipage}{\linewidth}
\centering
\putpie{}{Column1}\hfill
\putpie{}{Column2}\hfill
\putpie{}{Column3}\hfill
\putpie{}{Column4}\hfill
\putpie{}{Column5}\\
\putpie{\pie{}{41/inlined,13/noninlined}}{benchmark}\hfill
\putpie{\pie{}{12/inlined,78/noninlined}}{some}\hfill
\putpie{\pie{}{9/inlined,35/noninlined}}{other}\hfill
\putpie{\pie{}{71/inlined,8/noninlined}}{title}\hfill
\putpie{\pie{}{47/inlined,14/noninlined}}{benchmark}\\[2ex]
\putpie{\pie{}{34/inlined,34/noninlined}}{perhaps}\hfill
\putpie{\pie{}{4/inlined,65/noninlined}}{different}\hfill
\putpie{\pie{}{23/inlined,32/noninlined}}{words}\hfill
\putpie{\pie{}{17/inlined,13/noninlined}}{benchmark}\hfill
\putpie{\pie{}{34/inlined,13/noninlined}}{benchmark}\\[2ex]
\putpie{\pie{}{50/inlined,50/noninlined}}{title2}\hfill
\putpie{\pie{}{21/inlined,12/noninlined}}{benchmark}\hfill
\putpie{\pie{}{34/inlined,43/noninlined}}{and}\hfill
\putpie{\pie{}{43/inlined,11/noninlined}}{other}\hfill
\putpie{\pie{}{66/inlined,22/noninlined}}{word}
\end{minipage}\quad
\begin{minipage}{3cm}
\raggedleft
\begin{tikzpicture}[remember picture]
\legend{{Inlined}/inlined, {Not inlined}/noninlined}
\end{tikzpicture}%
\end{minipage}}
\end{figure}

\end{document}

enter image description here

As a side note, I changed from the deprecated \tikzstyle to \tikzset; also, \footnotesize is not a command with arguments, but a font switch so it must be used as {\footnotesize text} (the braces are to keep the effect local, and \par must be added before leaving the group for long paragraph texts.)

  • when I change the % of inlined or noninlined the text alignment is gone ? – Michal Feb 22 '14 at 20:53
  • 1
    @Michal please see my updated answer. – Gonzalo Medina Feb 23 '14 at 2:20
  • Thanks, works perfectly! How can I put a title for the entire column? I've tried using \begin{tikzpicture} \node (title) at (0.81,2.31) {\bf{Clojure}}; \node (title) at (2.69,2.31) {\bf{Java}}; \node (title) at (4.69,2.31) {\bf{JavaScript}}; \node (title) at (6.69,2.31) {\bf{JRuby}}; \node (title) at (8.69,2.31) {\bf{Jython}}; \node (title) at (10.69,2.31) {\bf{Scala}}; \end{tikzpicture} but it failed. – bekon Feb 24 '14 at 13:53
  • @bekon you can use an additional row of \putpies with empty content and just the title: \putpie{}{Column1}\hfill \putpie{}{Column2}\hfill \putpie{}{Column3}\hfill \putpie{}{Column4}\hfill \putpie{}{Column5}\\ Please see my updated answer. – Gonzalo Medina Feb 24 '14 at 14:54

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.