2

There's a nice answer to a pie chart question over here. I tried to bend it to my needs but found some aspects difficult. Specifically:

  • I'd like to be able to manually adjust the labels.

    • Rather than adding the degree labels (\newcommand{\degre}{$^\circ$}, I assume), I just want to be able to write something in manually, like a year or date or note or the variable name for instance.

    • I'd liked to have the option of replacing the percentage labels with something else too, like the actual value shown in the legend perhaps.

    • And finally, the numbers aren't formatted nicely. For instance, the value 1236 should ideally be written as 1,236.


Is this kind of customization possible? There are various similar questions about other pie chart designs, but this design is a bit different to most I've seen. Anyway the current code is below.


PS: I kept getting lost in it, so to make reading a bit quicker and easier, I've set: \begin{document} through \end{document} in bold, and:
value list={149/A,1236/R+L+D,740/N+F,346/C,75/E} in italics, so you can identify it at a glance.


chart

\documentclass[margin=5pt]{article}
\usepackage[svgnames]{xcolor}
\usepackage{tikz,fourier,ifthen}
\usetikzlibrary{calc}

\newcommand{\degre}{$^\circ$}

\colorlet{color0}{blue!40}
\colorlet{color1}{orange!60}
\colorlet{color2}{DarkGreen!40}
\colorlet{color3}{yellow!60}
\colorlet{color4}{red!60}
\colorlet{color5}{blue!60!cyan!60}
\colorlet{color6}{cyan!60!yellow!60}
\colorlet{color7}{red!60!cyan!60}
\colorlet{color8}{red!60!blue!60}
\colorlet{color9}{orange!60!cyan!60}


\makeatletter
    \tikzset{%
        dc tag/.style={align=center},
        dc legend/.style={align=left,anchor=west},
        dc sector/.style={fill=\Cj,line join=round}
        }

    \pgfkeys{/DiagCirc/.cd,
        % list of \Name/Value
        value list/.store in=\Value@list,
        % circular : 360 - semi circular 180
        angle max/.store in=\Angle@max,
        angle max=360,
        % radius of the diagram
        radius/.store in=\R@dius,
        radius=4cm,
        % composition of the legend
        % \V value
        % \N name
        % \P percent
        % \A angle
        % \Cj color
        legend/.store in=\L@gend,
        legend=,
        % location of the legend
        legend location/.store in=\Legend@Loc,
        legend location={($(\R@dius,\R@dius)+(.5,-.5)$)},   
        % poisition of the node in the sector
        % 0 center, 1 on the edge, 1.++ external
        factor/.store in=\F@ctor,
        factor=.80,
        % composition of the node in the sector
        tags/.store in=\T@gs,
        tags=,
        % correction of round errors in percents
        percent corr/.store in=\C@rrP,
        percent corr=,
        % correction of round errors in angles
        angle corr/.store in=\C@rrA,
        angle corr=,
        % individual shift
        shift sector/.store in=\Shift@j,
        shift sector=,
        % more nodes in the sectors, or new legeng
        sup loop/.store in=\Sup@Loop,
        sup loop=,
        % code of the diagram
        diagram/.code={%
        % Calculation of the sum
        \pgfmathsetmacro\S@m{0}
        \foreach \i/\y in \Value@list {\xdef\S@m{\S@m+\i}}  
        \pgfmathsetmacro\S@m{\S@m}
        \pgfmathsetmacro\C@eff{\Angle@max/\S@m}

        % beginning of the first sector
        \xdef\@ngleA{0}

        % main loop
        \foreach \V/\N [count=\j from 0] in \Value@list {%

        % calculation of the current angle
        \pgfmathsetmacro\A{\V*\C@eff}

        % superior limit of the sector
        \pgfmathsetmacro\@ngleB{\@ngleA+\A} ;

        % mean angle
        \pgfmathsetmacro\MedA{(\@ngleA+\@ngleB)/2} ;        

        % color
        \pgfmathtruncatemacro\@k{mod(\j,10)}
        \def\Cj{color\@k}

        % individual shift
        \ifthenelse{\equal{\Shift@j}{}}{%
        \edef\Sh@ft{0}}{%
        \pgfmathparse{array({\Shift@j},\j)}
        \edef\Sh@ft{\pgfmathresult} 
        }

        % drawing of the sector
        \draw[dc sector,shift={(\MedA:\Sh@ft)}] (0,0)
            -- (\@ngleA:\R@dius) arc (\@ngleA:\@ngleB:\R@dius)
                node[midway] (DC\j) {} -- cycle ;

        % low limit of the next sector
        \xdef\@ngleA{\@ngleB} ;

        % current percent correction
        \pgfmathtruncatemacro\P{round(\V/\S@m*100)}
        \ifthenelse{\equal{\C@rrP}{}}{}{%
            \pgfmathparse{array({\C@rrP},\j)}
            \pgfmathtruncatemacro\P{\P+\pgfmathresult}
        }
        \edef\P{\P\,\%}

        % current angle and corection
        \pgfmathtruncatemacro\A{round(\A)}
        \ifthenelse{\equal{\C@rrA}{}}{}{%
            \pgfmathparse{array({\C@rrA},\j)}
            \pgfmathtruncatemacro\A{\A+\pgfmathresult}  
            \edef\A{\A\,\degre}
        }

        % the sector node
        \ifthenelse{\equal{\T@gs}{}}{}{%
        \DiagNode[dc tag]{\F@ctor} {\T@gs} ;
        }

        % the legend
        \ifthenelse{\equal{\L@gend}{}}{}{%
        \begin{scope}[shift=\Legend@Loc]
        \draw[fill=\Cj] (0,-.5*\j)
                rectangle ++(.25,.25) ++(0,-.15)
                node[dc legend] {\strut\L@gend} ;
        \end{scope}
        }

        % some more stuff
        \Sup@Loop ;
        }

        } % end of diagram code
    }
\makeatother

% Node on the \j sector
\newcommand{\DiagNode}[2][]{\node[#1] at ($(0,0)!#2!(DC\j)$)}

\begin{document}

\begin{tikzpicture}
\path[%
    % style options
    dc sector/.append style={shift={(\MedA:5pt)}}, % shift all sectors
    dc dtag/.append style={},
    dc legend/.append style={text width=2cm, align=right},
    every pin/.style={fill=\Cj,draw=\Cj!50!black,thick},
    % diagram options
    /DiagCirc/.cd,
    value list={149/A,1236/R+L+D,740/N+F,346/C,75/E},
    angle max=180,             % semi-circular
    angle corr={0,1,0,0,0},    % correct round angle error
    legend=\N\ :\hfill \V,     % custom legend
    factor=.9,
    percent corr={0,-1,0,0,0}, % correct round percent error
    shift sector={0,0,.3,0,0}, % shift individual sector
    tags=\P,                   % custom sector nodes
    sup loop={% custom features :       
        %\DiagNode{1.1} {\N};  % some other sector nodes
        % or something else
        \def\Pin{{10,40,150,120,150}}
        \pgfmathparse{array(\Pin,\j)}
        \edef\Pinj{\pgfmathresult}
        \node[pin=\Pinj:\A] at (DC\j) {}  ;
        },
    diagram] ;

\end{tikzpicture}
\end{document}
  • Straight up solutions are welcome, but what would be really nice is if you could also explain a little bit about how it works, so anyone reading can maybe solve similar problems on their/my own in the future. Teach a man to fish and all that. No pressure though, just a suggestion. – voices Apr 9 at 10:59
2

First of all, please limit your scope of question to one at a time. In my opinion, your questions has sub-questions ;).

Having said that I think you can simply use pgf-pie to achieve your first two parts:

\documentclass{standalone}
\usepackage{pgf-pie}
\begin{document}
    \begin{tikzpicture}
    \pie[ sum =1000 , after number =$^\circ$, radius
    =2,  text = legend]{200/A+B+C , 500/E+G+H, 300/F }
    \end{tikzpicture}
\end{document}

and for the 3rd part, I leave it to the tikzperts :).

enter image description here

Just make the sum=2000 and you get a semi-circle as in

\documentclass{standalone}
\usepackage{pgf-pie}
\begin{document}
    \begin{tikzpicture}
    \pie[ sum =2000 , after number =$^\circ$, radius
    =2,  text = legend]{200/A+B+C , 500/E+G+H, 300/F }
    \end{tikzpicture}
\end{document}

enter image description here

  • Everything has subquestions, it depends how you slice it. I was trying to be thorough is all. But at it's core, it's simply about exerting control over the textual elements of a graph. If it helps, think of it as "how can we customize the various texts of this pie chart?" or something like that. That said, this actually looks pretty nice. Can it do the extra labels though, and half pies (semi-circles) too? I have no need for displaying degrees either. but keep this up, it's still nice information. – voices Apr 9 at 12:33
  • 2
    Please check updated answer. It can do many things ;). – Raaja Apr 9 at 12:48
0

Customization pie chart with plain TikZ. The code is long, but mostly done by copy-paste. You can shorten the code with foreach. I am willing to explain more if asked.

enter image description here

\documentclass[tikz,border=5mm]{standalone}
\begin{document}
\begin{tikzpicture}  
% for legends
\tikzset{box/.pic={
\draw[fill=#1] (-.2,-.2) rectangle (.2,.2);
}}

\begin{scope}[shift={(6,2)}]
\path
(0,0)     pic[fill=red!50]{box}
          node[right=2mm]{E :}
          +(0:2.8) node[left]{75}
++(90:.6) pic[fill=yellow!50]{box} 
          node[right=2mm]{C :}
          +(0:2.8) node[left]{346}
++(90:.6) pic[fill=teal!50]{box}                  
          node[right=2mm]{N+F :}
          +(0:2.8)node[left]{740}          
++(90:.6) pic[fill=orange!50]{box} 
          node[right=2mm]{R+L+D :}
          +(0:2.8) node[left]{1236}
++(90:.6) pic[fill=blue!50]{box} 
          node[right=2mm]{A :}
          +(0:2.8) node[left]{149};
\end{scope}

\def\r{5} % radius of the pie chart

% each scope is a shifted piece of the pie
\begin{scope}[shift={(0:.2)}]
\draw[fill=blue!50] 
(0:\r) arc(0:11:\r)--(0,0)--cycle;
\draw[gray!50] (5.5:\r) 
node[left,black]{$6\%$}--+(30:1) 
node[draw=black,text=black,fill=blue!50]
{$11^{\circ}$};
\end{scope}

\begin{scope}[shift={(50:.2)}]
\draw[fill=orange!50] 
(11:\r) arc(11:99:\r)--(0,0)--cycle;
\draw[gray!50] (55:\r) 
node[below left,black]{$48\%$}--+(40:1) 
node[draw=black,text=black,fill=orange!50]
{$88^{\circ}$}; 
\end{scope}

\begin{scope}[shift={(120:.5)}]
\draw[fill=teal!50] 
(99:\r) arc(99:99+52:\r)--(0,0)--cycle;
\draw[gray!50] (125:\r) 
node[below right,black]{$29\%$}--+(150:1) 
node[draw=black,text=black,fill=teal!50]
{$52^{\circ}$}; 
\end{scope}

\begin{scope}[shift={(150:.3)}]
\draw[fill=yellow!50] 
(151:\r) arc(151:151+24:\r)--(0,0)--cycle;
\draw[gray!50] (165:\r) node[right,black]{$14\%$}--+(150:1) 
node[draw=black,text=black,fill=yellow!50]
{$24^{\circ}$}; 
\end{scope}

\begin{scope}[shift={(180:.3)}]
\draw[fill=red!50] 
(175:\r) arc(175:180:\r)--(0,0)--cycle;
\draw[gray!50] (177.5:\r) node[right,black]{$3\%$}--+(150:1) 
node[draw=black,text=black,fill=red!50]
{$5^{\circ}$}; 
\end{scope}

\end{tikzpicture}
\end{document}

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.