Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

It seems that pgfplots users don't like pie charts but sometimes we can't go without (for some reasons). So I was wondering if there was a way to make what is called a donut chart.

For example one like this:

Image of an donut

share|improve this question
    
Such an example can be found in the user manual of TikZ. –  Marco Daniel May 17 '12 at 15:24
11  
Never do this in 3D. Ever. Please. See section 7.6 of the PGF/TikZ manual for reasons why not. Basically it skews the data. –  qubyte May 17 '12 at 15:41
    
Pie charts are fine by the way. I don't use them but I'm not in a field that deals with percentages. –  qubyte May 17 '12 at 15:43
    
I agree with you Mark but this time it's only for a design purpose not for a technically use. I swear )) Concerning Marco's comment are you talking about this one : ftp.snt.utwente.nl/pub/software/tex/graphics/pgf/base/doc/… Because i only found a picture about it, that's all. –  Rave May 17 '12 at 15:54
3  
Have a look at How to produce a ring chart? or pgf-pie –  Marco May 17 '12 at 16:33

3 Answers 3

up vote 39 down vote accepted

Like T. Tantau and Mark S. Everitt, I think it's a bad thing to do this. I don't understand if you want to use pgfplots or pgf plots ? It's not exactly the same things. The code would be better if yshift for the shadow is calculated in function of the height of the picture.

Update 2

Some corrections, complete and clean the code.

enter image description here

\documentclass{scrartcl}
\usepackage{tikz}
\usetikzlibrary{fadings}

\begin{document}
\begin{tikzpicture}[fading style/.style={preaction={fill=#1,opacity=.8,
                   path fading=circle with fuzzy edge 20 percent}}]

  \begin{scope}[xscale=5,yscale=3]
    \path[fading style=black,transform canvas={yshift=-40pt}] (0,0) circle (1cm);         
    \fill[gray](0,0) circle (0.5cm);  
    \path[fading style=white,transform canvas={yshift=-16mm}] (0,0) circle (0.65cm);    
    \draw[yshift=-3mm](0,0) circle (0.5cm); 

    \shadedraw[top color=green!20!gray,,bottom color=green!5!black,draw=black,very thin]  
        (90:0.5cm)--++(0,-3mm) arc(90:-5:0.5cm)--++(0,3mm)  arc(-5:90:0.5cm)--cycle;      
    \shadedraw[top color=orange!20!gray,bottom color=orange!5!black,draw=black,very thin]   
        (-105:0.5cm)--++(0,-3mm) arc(-105:-225 :0.5cm)--++(0,3mm)  arc(-225:-105:0.5cm)--cycle;   
    \shadedraw[top color=blue!50!white,,bottom color=blue!5!black,draw=black,very thin]   
        (135 :0.5cm)--++(0,-3mm) arc(135:90:0.5cm)--++(0,3mm)  arc(90:135:0.5cm)--cycle;  

    \begin{scope}[draw=black,thin]
       \fill[green!20!gray](90 :0.5cm)--(90:1cm) arc(90:-5:1cm)--(-5:0.5cm) arc(-5:90 :0.5cm);     
       \fill[white!20!gray](-5 :0.5cm)--(-5:1cm) arc(-5:-105 :1cm)--(-105:0.5cm) arc(-105:-5:0.5cm);        
       \fill[orange!20!gray](-105:0.5cm)--(-105:1cm) arc(-105:-225 :1cm)--(-225:0.5cm) arc(-225:-105:0.5cm);
       \fill[blue!50!white](135:0.5cm)--(135 :1cm) arc(135:90:1cm)--(90:0.5cm) arc(90:135:0.5cm);
    \end{scope}
    \draw[thin,black](0,0) circle (0.5cm);   

    \shadedraw[bottom color=orange!20!gray,top color=orange!5!black,draw=black,very thin]   
    (-180:1cm) --++(0,-3mm) arc (-180:-105 :1cm) -- ++(0,3mm)  arc (-105 :-180  :1cm) -- cycle;  
    \shadedraw[bottom color=white!20!gray,top color=white!5!black,draw=black,very thin]   
    (-105:1cm) --++(0,-3mm) arc (-105:0 :1cm) -- ++(0,3mm)  arc (0 :-105  :1cm) -- cycle;  

      \draw[very thin] (90:0.5cm) -- (90:1cm)
            (-5:0.5cm) -- (-5:1cm)
            (-105:0.5cm) -- (-105:1cm)
            (135:0.5cm) -- (135 :1cm)
            (0,0) circle (1cm)
            (90:0.5cm)  arc (90 :135:0.5cm);

    \coordinate (left border) at (1.5cm,0cm); 
    \coordinate (right border) at (-1.5cm,0cm); 
    \coordinate (l1) at (43.5:0.75 cm);
    \coordinate (l2) at (-55:0.75 cm); 
    \coordinate (l3) at (117.5:0.75 cm);
    \coordinate (l4) at (-160:0.75 cm);

    \begin{scope}[lab/.style={gray!50!black,thick,draw}]
        \fill[lab] (l1) circle(.4mm) -- (l1-| left border) node[anchor=south east] {Corporate}
                                                           node[anchor=north east] {26\%};         
       \fill[lab] (l2) circle(.4mm) -- (l2-| left border)  node[anchor=south east] {Plastique}
                                                           node[anchor=north east] {28\%}; 
       \fill[lab] (l3) circle(.4mm) -- (l3-| right border) node[anchor=south west] {Rhodia}
                                                           node[anchor=north west] {12.5\%};         
       \fill[lab] (l4) circle(.4mm) -- (l4-| right border) node[anchor=south west] {Chimique}
                                                           node[anchor=north west] {43.5\%}; 
    \end{scope}
   \end{scope}  
\end{tikzpicture}    
\end{document}        

Attempt to automate version 4

macro \piechartthreed

Two arguments #1 for the options #2 list of angles and colors (a1/col1,a2/col2,etc...)

Options scale scale the pie chart, mix color used to color the sector, background color color for the background, name used to name the point at the "center" of each sector.

\documentclass{scrartcl}
\usepackage{tikz}
\usetikzlibrary{fadings}

\pgfkeys{%
/piechartthreed/.cd,
scale/.code                =  {\def\piechartthreedscale{#1}},
mix color/.code            =  {\def\piechartthreedmixcolor{#1}},
background color/.code     =  {\def\piechartthreedbackcolor{#1}},
name/.code                 =  {\def\piechartthreedname{#1}}}

 \newcommand\piechartthreed[2][]{% 
   \pgfkeys{/piechartthreed/.cd,
     scale            = 1,
     mix color        = gray,
     background color = white,
     name             = pc} 
  \pgfqkeys{/piechartthreed}{#1}
  \begin{scope}[scale=\piechartthreedscale] 
  \begin{scope}[xscale=5,yscale=3] 
     \path[preaction={fill=black,opacity=.8,
         path fading=circle with fuzzy edge 20 percent,
         transform canvas={yshift=-15mm*\piechartthreedscale}}] (0,0) circle (1cm);
    \fill[gray](0,0) circle (0.5cm);  
     \path[preaction={fill=\piechartthreedbackcolor,opacity=.8,
          path fading=circle with fuzzy edge 20 percent,
          transform canvas={yshift=-10mm*\piechartthreedscale}}] (0,0) circle (0.5cm);
     \pgfmathsetmacro\totan{0} 
     \global\let\totan\totan 
     \pgfmathsetmacro\bottoman{180} \global\let\bottoman\bottoman 
     \pgfmathsetmacro\toptoman{0}   \global\let\toptoman\toptoman 
     \begin{scope}[draw=black,thin]
     \foreach \an/\col [count=\xi] in {#2}{%
     \def\space{ } 
        \coordinate (\piechartthreedname\space\xi) at (\totan+\an/2:0.75cm); 
        \ifdim 180pt>\totan pt 
         \ifdim 0pt=\toptoman pt
            \shadedraw[left color=\col!20!\piechartthreedmixcolor,
                       right color=\col!5!\piechartthreedmixcolor,
                       draw=black,very thin] (0:.5cm) -- ++(0,-3mm) arc (0:\totan+\an:.5cm) 
                                                       -- ++(0,3mm)  arc (\totan+\an:0:.5cm);
            \pgfmathsetmacro\toptoman{180} 
            \global\let\toptoman\toptoman         
            \else
            \shadedraw[left color=\col!20!\piechartthreedmixcolor,
                       right color=\col!5!\piechartthreedmixcolor,
                       draw=black,very thin](\totan:.5cm)-- ++(0,-3mm) arc(\totan:\totan+\an:.5cm)
                                                        -- ++(0,3mm)  arc(\totan+\an:\totan:.5cm); 
          \fi
        \fi   
        \fill[\col!20!gray,draw=black] (\totan:0.5cm)--(\totan:1cm)  arc(\totan:\totan+\an:1cm)
                                     --(\totan+\an:0.5cm) arc(\totan+\an:\totan :0.5cm);     
       \pgfmathsetmacro\finan{\totan+\an}
       \ifdim 180pt<\finan pt 
         \ifdim 180pt=\bottoman pt
            \shadedraw[left color=\col!20!\piechartthreedmixcolor,
                       right color=\col!5!\piechartthreedmixcolor,
                       draw=black,very thin] (180:1cm) -- ++(0,-3mm) arc (180:\totan+\an:1cm) 
                                                       -- ++(0,3mm)  arc (\totan+\an:180:1cm);
            \pgfmathsetmacro\bottoman{0}
            \global\let\bottoman\bottoman
            \else
            \shadedraw[left color=\col!20!\piechartthreedmixcolor,
                       right color=\col!5!\piechartthreedmixcolor,
                       draw=black,very thin](\totan:1cm)-- ++(0,-3mm) arc(\totan:\totan+\an:1cm)
                                                        -- ++(0,3mm)  arc(\totan+\an:\totan:1cm); 
          \fi
        \fi
        \pgfmathsetmacro\totan{\totan+\an}  \global\let\totan\totan 
       } 
    \end{scope}
    \draw[thin,black](0,0) circle (0.5cm);
   \end{scope}  
\end{scope}
}

\begin{document} 
 \pagecolor{orange!50}
 \begin{tikzpicture}
   \piechartthreed[scale=0.8,
                   background color=orange!50,
                   mix color= darkgray]
                   {40/green,60/blue,90/red,50/orange,120/yellow}
   \foreach \i in {1,...,5} { \fill (pc \i) circle (.5mm);}
   \draw[darkgray] (pc 1)  -- ++(4,0) coordinate (s1) node[anchor=south east] {Sector 1}
                                                      node[anchor=north east] {11\%};
   \draw[darkgray] (pc 5)  -- (pc 5 -| s1) node[anchor=south east] {Sector 5}
                                                      node[anchor=north east] {33\%}; 
   \draw[darkgray] (pc 2)  -- ++(1,1) coordinate (s2) -- (s2 -| s1) node[anchor=south east] {Sector 2}
                                                      node[anchor=north east] {17\%}; 
   \draw[darkgray] (pc 3)  -- ++(-4,0) coordinate (s3) node[anchor=south west] {Sector 3}
                                                      node[anchor=north west] {14\%};
   \draw[darkgray] (pc 4)  -- ++(-1,-1) coordinate (s4) --(s4 -| s3) node[anchor=south west] {Sector 4}
                                                      node[anchor=north west] {25\%};
 \end{tikzpicture}

\end{document}

enter image description here

todo

Clean the code and add some options.

share|improve this answer
    
The best looking one so far –  Martin H Jun 12 '12 at 9:41
    
Deserves a gold medal. –  Marc van Dongen Oct 2 '12 at 14:35
    
Is it possible to make it more shinny? –  wererabit Apr 18 '13 at 21:07
    
This is really awesome! –  carsten Jun 11 at 20:34
    
Addendum: I also wanted the colors a bit more shiny. I was able to achieve this by adding pgfkeys for mix rate low and mix rate high and replace the values 20/5 in the code with \piechartthreedmixratehigh/\piechartthreedmixratelow. Then setting the high/low mix rates to 80/60 makes nice and shiny colors. You also need to replace the remaining occurence of gray in \col!20!gray with \piechartthreedmixcolor –  carsten Jun 11 at 21:02

run it with xelatex or latex->dvips->ps2pdf

\documentclass{article}
\usepackage[dvipsnames,svgnames]{pstricks}
\usepackage{pst-solides3d}

\begin{document}
\begin{pspicture}(-3.5,-1.5)(3.5,1.5)
\psset[pst-solides3d]{viewpoint=50 20 20 rtp2xyz,
  Decran=20}
\psSolid[object=anneau,h=1,R=8,r=6,ngrid=90,grid=false,
  fcol= 0 1  19 { (Red) } for 
       20 1  59 { (LimeGreen) } for 
       60 1 179 { (Blue) } for 
      180 1 299 { (Sepia) } for 
      300 1 359 { (BrickRed) } for 
  ](0,0,0)
\end{pspicture}
\end{document}

enter image description here

or with grid lines:

\documentclass{article}
\usepackage[dvipsnames,svgnames]{pstricks}
\usepackage{pst-solides3d}

\begin{document}
\begin{pspicture}(-3.5,-1.5)(3.5,1.5)
\psset[pst-solides3d]{viewpoint=50 20 20 rtp2xyz,
  Decran=20}
\psSolid[object=anneau,h=1,R=8,r=6,ngrid=90,linewidth=0.1pt,
  fcol= 0 1  19 { (Red) } for 
       20 1  59 { (LimeGreen) } for 
       60 1 179 { (Blue) } for 
      180 1 299 { (Sepia) } for 
      300 1 359 { (BrickRed) } for 
  ](0,0,0)
\end{pspicture}
\end{document}

enter image description here

share|improve this answer
1  
The most elegant code so far. –  schmendrich Jun 12 '12 at 12:37

Here is a first version. So far you can only define the angles of the individual sectors. In the center of each sector there is a node n(sector number) which you can use for labeling.

\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm]{geometry}
\usepackage{tikz}
\usetikzlibrary{calc}

\global\edef\lastangle{0}
\newcounter{sectornumber}

\newcommand{\ring}[1]{% angles
\setcounter{sectornumber}{1}
\foreach \x in {#1}
{   \pgfmathsetmacro{\na}{\lastangle+\x}
    \fill[red,draw=black] (\lastangle:3) arc (\lastangle:\na:3) -- ++(0,0,0.5) arc (\na:\lastangle:3) -- cycle;
    \fill[blue,draw=black] (\lastangle:4) arc (\lastangle:\na:4) -- ++(0,0,0.5) arc (\na:\lastangle:4) -- cycle;
    \global\edef\lastangle{\na}
}
\global\edef\lastangle{0}
\foreach \x in {#1}
{   \pgfmathsetmacro{\na}{\lastangle+\x}
    \fill[green,draw=black] (0,0,0.5) ++(\lastangle:3) arc (\lastangle:\na:3) -- ++(\na:1) arc (\na:\lastangle:4) -- cycle;
    \node (n\thesectornumber) at ($(0,0,0.5)+(\lastangle+\x/2:3.5)$) {};
    \stepcounter{sectornumber}
    \global\edef\lastangle{\na}
}
}

\begin{document}

\begin{tikzpicture}[x={(0.866cm,0.5cm)},y={(-0.866cm,0.5cm)},z={(0cm,1cm)}]
\ring{10,20,30,40,50,60,70,80}
\draw[thick] (n1) -- ++(5:2) node[above right] {Bla 1};
\draw[thick] (n3) -- ++(45:2) node[above] {Bla 2};
\draw[thick] (n6) -- ++(180:2) node[left] {Bla 3};
\draw[thick] (n8) -- ++(-45:2) node[right] {Bla 4};
\end{tikzpicture}

\end{document}

enter image description here


Edit 1: a revised version, with choosable colors and shaded edges. It only works for quite flat rings:

\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm]{geometry}
\usepackage{tikz}
\usetikzlibrary{calc,shapes,shadows}

\global\edef\lastangle{0}
\newcounter{sectornumber}

\newcommand{\ring}[4]{% angles&colors, inner, outer radius, height
\begin{scope}[x={(0.866cm,0.5cm)},y={(-0.866cm,0.5cm)},z={(0cm,1cm)}]
\global\edef\lastangle{0}
\setcounter{sectornumber}{1}
\foreach \x/\ringcolor in {#1}
{   \pgfmathsetmacro{\na}{\lastangle+\x*3.6}
    \colorlet{darkercolor}{\ringcolor!60!black}
    \colorlet{darkestcolor}{\ringcolor!20!black}
    \shadedraw[top color=darkercolor,bottom color=darkestcolor,draw=darkercolor] (\lastangle:#2) arc (\lastangle:\na:#2) -- ++(0,0,#4) arc (\na:\lastangle:#2) -- cycle;
    \shadedraw[top color=darkercolor,bottom color=darkestcolor,draw=darkercolor] (\lastangle:#3) arc (\lastangle:\na:#3) -- ++(0,0,#4) arc (\na:\lastangle:#3) -- cycle;
    \global\edef\lastangle{\na}
}
\global\edef\lastangle{0}
\foreach \x/\ringcolor in {#1}
{   \pgfmathsetmacro{\na}{\lastangle+\x*3.6}
    \colorlet{darkercolor}{\ringcolor!60!black}
    \colorlet{darkestcolor}{\ringcolor!20!black}
    \fill[\ringcolor,draw=darkercolor] (0,0,#4) ++(\lastangle:#2) arc (\lastangle:\na:#2) -- ++(\na:#3-#2) arc (\na:\lastangle:#3) -- cycle;
    \pgfmathsetmacro{\nodepos}{(#3+#2)*0.5}
    \node (n\thesectornumber) at ($(0,0,#4)+(\lastangle+\x*1.8:\nodepos)$) {};
    \stepcounter{sectornumber}
    \global\edef\lastangle{\na}
}
\end{scope}
}

\begin{document}

\begin{tikzpicture}
\ring{5/red!80!gray,15/blue!80!gray,15/yellow!80!gray,25/green!80!gray,10/orange!80!gray,10/violet!80!gray,5/brown!80!gray,15/cyan!80!gray}{3}{4}{0.5}
\foreach \x/\label in {1/Kill Bill,2/The Godfather,3/Garden State,4/Sin City,5/Fight Club,6/Star Trek VI,7/Terminator 2,8/Gran Torino}
{   \draw[thick] (n\x) -- ++(0,0.5) node[fill=white,draw,rounded rectangle,inner sep=2pt,thin,fill opacity=0.7,text opacity=1] {\tiny\label};
}
\end{tikzpicture}

\begin{tikzpicture}[x={(0.866cm,0.5cm)},y={(-0.866cm,0.5cm)},z={(0cm,1cm)}]
\ring{5/red!80!gray,15/blue!80!gray,15/yellow!80!gray,25/green!80!gray,10/orange!80!gray,10/violet!80!gray,5/brown!80!gray,15/cyan!80!gray}{2}{4}{2}
\foreach \x/\label in {1/Kill Bill,2/The Godfather,3/Garden State,4/Sin City,5/Fight Club,6/Star Trek VI,7/Terminator 2,8/Gran Torino}
{   \draw[thick] (n\x) -- ++(0.5,0.5) node[fill=white,draw,rounded rectangle,inner sep=2pt,thin,fill opacity=0.7,text opacity=1] {\tiny\label};
}
\end{tikzpicture}

\end{document}

enter image description here

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.