1

I'm trying to create a pie chart similar to this one. Reading the documentation for pgf-pie and it doesn't seem to have options for having multiple styles of text (text=pin, text=inside etc) for different texts within the same chart. Currently I've only been able to create the this chart. I would ideally want text=inside to be applied to the bigger categories and text=pin for the smaller categories to have their percentages taken out of the chart itself because they are unreadable as they are right now.

Current code:

\documentclass[border=5mm]{standalone}
\usepackage{pgf-pie}
\usepackage{etoolbox}
\makeatletter
\patchcmd{\pgfpie@slice}% this is the macro we're patching
{\scalefont{#3}\shortstack{#4\\\beforenumber#3\afternumber}}% find this
{\scalefont{#3}#4}% and replace with this
{}{}
\makeatother
\begin{document}

\begin{tikzpicture}
\pie[before number =, after number = {\%},text=pin, ]{
    37.7/Investment Scams,
    21.1/{Dating \& Romance Scams},
    10.2/False Billing, 
    6.5/Threats,
    4.8/Online Shopping Scams,
    4.5/Remote Access Scams,
    3.1/Classified Scams,
    2.2/Health \& Medical Products,
    1.8/Identity Theft,
    1.2/Hacking,
    1.2/Phishing,
    1.0/Unexpected Prize \& Lottery,
    0.8/Inheritance Scams,
    0.7/Jobs and Employment Scams,
    0.6/Betting and Sports Investment Scams,
    2.4/Other Scams
    }
\end{tikzpicture}

\end{document}
1
  • One of the guidelines in making pie charts is not to use too many categories (see for example act-on.com/blog/…). But taking the percentages out should be doable, I'll try some things out (hopefully today).
    – Marijn
    Mar 11, 2021 at 12:30

1 Answer 1

1

As mentioned in the comments I would advise against using a pie chart for a large number of categories, because it becomes unreadable very quickly. A bar chart might be a better choice, or grouping small categories together.

However, you can adjust the behavior of pgf-pie to improve the result somewhat, by patching/redefining the relevant macros. Note that for this answer I used the current version of pgf-pie from Github (https://github.com/pgf-tikz/pgf-pie, dated December 26th 2020), which is newer than the version currently on CTAN (May 28th, 2020). This is relevant because the patches below only work for the Github version (which will at some point be uploaded to CTAN presumably).

The first modification is to remove the percentages from the slice for small values (below 5%). This is done by a redefinition of the macro \pgfpie@numbertext This is a small macro so it is not really needed to apply a patch, instead the full macro can be redefined with \def. The idea is to check with pgfmath if the argument is bigger than 5, and use \ifnum to conditionally print the number. Note that \ifnum cannot be used directly because \ifnum is an integer comparison and the percentages may be decimal numbers.

The second modification is to add the percentage behind the label automatically for slices with small values. This is a bit more involved because it requires modification of \pgfpie@slice in two places, first to define a temporary macro with or without the percentage based on the value, and second to use that macro for the slice label instead of argument #4. This is done by two patches, first a \pretocmd to define the label at the start of \pgfpie@slice and then a \patchcmd to change the label printing code in the middle of \pgfpie@slice.

Note that you can also achieve the result of the second modification manually by adding the percentages to the relevant labels in the call to \pie.

MWE:

\documentclass[border=5mm]{standalone}
\usepackage{pgf-pie} % version: https://github.com/pgf-tikz/pgf-pie Dec 26, 2020
\usepackage{etoolbox}
\makeatletter
\pretocmd{\pgfpie@slice}{% define label text with percentages for small values
\pgfmathparse{#3 > 5}%
\ifnum\pgfmathresult=1 %
\def\txtlabel{#4}% original label for large values
\else%
\def\txtlabel{#4 (#3\%)}% label with percentage for small values
\fi%
}{\message{define label patch ok}}{\message{define label patch failed}}

\patchcmd{\pgfpie@slice}% use label text instead of original argument #4
{\pgfpie@text={\pgfpie@midangle:#4}}%
{\pgfpie@text={\pgfpie@midangle:\txtlabel}}%
{\message{add pct patch ok}}%
{\message{add pct patch failed}}%

\def\pgfpie@numbertext#1{% don't print percentage in slice for small values
  \pgfpie@ifhidenumber{}{%
    \pgfmathparse{#1 > 5}%
    \ifnum\pgfmathresult=1 %
    \pgfpie@beforenumber#1\pgfpie@afternumber%
    \fi
  }%
}
\makeatother
\begin{document}

\begin{tikzpicture}
\pie[before number =, after number = {\%},text=pin, ]{
    37.7/Investment Scams,
    21.1/{Dating \& Romance Scams},
    10.2/False Billing, 
    6.5/Threats,
    4.8/Online Shopping Scams,
    4.5/Remote Access Scams,
    3.1/Classified Scams,
    2.2/Health \& Medical Products,
    1.8/Identity Theft,
    1.2/Hacking,
    1.2/Phishing,
    1.0/Unexpected Prize \& Lottery,
    0.8/Inheritance Scams,
    0.7/Jobs and Employment Scams,
    0.6/Betting and Sports Investment Scams,
    2.4/Other Scams
    }
\end{tikzpicture}

\end{document}

Result:

enter image description here

The question asked to put the label inside for large values and pin for small values. However, in this example the labels are quite long, so the only slice where the label would actually fit is Investment Scams. Therefore I thought it would be better to pin all labels. Of course such a modification would also be possible by applying the same test (with \pgfmathparse and \ifnum) elsewhere in \pgfpie@slice.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .