6

Using the pie function in R, the labels appear outside of the pie. Is there a way to place labels inside each slice of the pie chart?

f=table(LETTERS[c(rep(1,7),rep(2,10),rep(3,5))])
pie(f)

It shows how to do this with ggplot here place-labels-on-pie-chart. Is there no way to do it with the pie function?

Edit: In response to some comments about the use of pie charts, I'd like to elaborate my intention with them. I'm actually just using the pie chart as part of a scatterplot matrix to visualize a whole data frame for regression. The matrix is set up as follows:

  • Lower panels
    Sample correlation numbers with the background colored darker for higher absolute correlation.
  • Upper panels
    • Scatterplots for numeric by numeric
    • Boxplots for numeric by factor
  • Diagonal panels
    • Histograms with normal densities for numeric
    • Pie chart for factor

See, I needed something for factors on the diagonal and decided on a pie chart. I decided to leave the labels out anyway and took off all axis labeling as well. I rather used darker colors for bigger pie slices... so perhaps it may be a bad way to display information but I think it works well for a factor variable, showing how the observations are proportioned across factor levels better than a barplot would do. The figure below describes the diabetes data set in the lars package.

diabetes data set

Community
  • 1
  • 1
StatGrrl
  • 225
  • 2
  • 9

1 Answers1

5

I don't think there is an easy way to do this as the label positions are hard coded - look at the end of

body(pie)

        if (!is.na(lab) && nzchar(lab)) {
            lines(c(1, 1.05) * P$x, c(1, 1.05) * P$y)
            text(1.1 * P$x, 1.1 * P$y, labels[i], xpd = TRUE, 
                adj = ifelse(P$x < 0, 1, 0), ...)
        }
    }
    title(main = main, ...)
    invisible(NULL)
}

But you can overwrite this section of the program

# create a new pie function to save overwriting original
newpie <- pie

# Tweak the label positions - changed 1.1 to 0.7
# also commented out the lines function - so that the  
# small lines next to the labels are not plot
newlbs <- quote(if (!is.na(lab) && nzchar(lab)) {
                   #lines(c(1, 1.05) * P$x, c(1, 1.05) * P$y)
                    text(0.7 * P$x, 0.7 * P$y, labels[i], xpd = TRUE, 
                                     adj = ifelse(P$x < 0, 1, 0), ...)
})

# add in the new lines of code - trial and error found the right position
body(newpie)[[22]][[4]][[7]] <- newlbs

newpie(f)

So seems a low of work but it get there and you would need to do a bit more work to angle or format the text.

(probably turn out there is an argument to do this)

user20650
  • 24,654
  • 5
  • 56
  • 91
  • 1
    Nice workaround. I bet it's so hard to change the pie chart because nobody in statistics should be using pie charts. ;-) – Rich Scriven Sep 17 '14 at 01:00
  • cheers Richard, Yes i was going to quote the `?pie` help - `Pie charts are a very bad way of displaying information` – user20650 Sep 17 '14 at 01:01
  • Pro tip: You can use `tail` on a function, i.e. `tail(pie, 9)` is equivalent to the `body` call that you probably had to scroll through. Of course, you still need `body<-` to change the body. – Rich Scriven Sep 17 '14 at 01:20
  • @RichardScriven; Thanks for the pointer - that is certainly neater. For overwriting the code, unfortunately the lines from `body` don't come out as single lines (`body(pie)[22]`) - is there a better way to do this, as above seemed terribly clumsy? – user20650 Sep 17 '14 at 01:35
  • I have never seen an alternative to `body(FUN)[[x]][[y]][[z]] <- ...`That's the way I do it and I haven't seen a better way yet – Rich Scriven Sep 17 '14 at 01:37
  • But I will mention that `rapply` and `grep` can be very useful in searching function bodies. `rapply` since most function bodies are nested lists – Rich Scriven Sep 17 '14 at 01:41
  • Yes, try `as.list(body(pie))`. `rapply` might not be good for `pie` though – Rich Scriven Sep 17 '14 at 01:58