ggplot pie chart labeling

15,693

Solution 1

For pie charts plotly works a lot easier than ggplot. Perhaps something like this:

library(plotly)

p <- plot_ly(alloc, labels = ~ltr, values = ~wght, type = 'pie',textposition = 'outside',textinfo = 'label+percent') %>%
  layout(title = 'Letters',
         xaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE),
         yaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE))

enter image description here

Solution 2

We can make it work with ggplot2 and the ggrepel package.

Unfortunately geom_text_repel() does not support a position = argument, so we have to calculate the starting position of the line by hand.

With your data.frame:

alloc$pos = (cumsum(c(0, alloc$wght)) + c(alloc$wght / 2, .01))[1:nrow(alloc)]

This calculates the mean point for each group (or obs, or whtvr you want to call it).

Plugging it in in the geom_text_repel's y aes gives a nice result:

library(ggplot2)
library(ggrepel)
ggplot(alloc, aes(1, wght, fill = ltr)) +
    geom_col(color = 'black', 
             position = position_stack(reverse = TRUE), 
             show.legend = FALSE) +
    geom_text_repel(aes(x = 1.4, y = pos, label = ltr), 
                    nudge_x = .3, 
                    segment.size = .7, 
                    show.legend = FALSE) +
    coord_polar('y') +
    theme_void()

I made some choices, as the use of text instead of label, the removal of the legend and the axes. Feel free to change them

Share:
15,693

Related videos on Youtube

AK88
Author by

AK88

Updated on June 14, 2022

Comments

  • AK88
    AK88 about 2 years

    I am struggling with getting the pie chart labels correct. Looked around and thought that I could easily implement what mathematicalCoffee did. So far I have this code:

    ltr = LETTERS[seq( from = 1, to = 26)]
    
    wght = runif(length(ltr))
    wght = wght/sum(wght)
    wght = round(wght, digits = 2)
    
    alloc = as.data.frame(cbind(ltr, wght))
    alloc$wght = as.numeric(as.character(alloc$wght))
    
    ggpie <- function (dat, by, totals) {
      ggplot(dat, aes_string(x=factor(1), y=totals, fill=by)) +
        geom_bar(stat='identity', color='black') +
        guides(fill=guide_legend(override.aes=list(colour=NA))) +
        coord_polar(theta='y') +
        theme(axis.ticks=element_blank(),
              axis.text.y=element_blank(),
              axis.text.x=element_text(colour='black'),
              axis.title=element_blank()) +
        ## scale_fill_brewer(palette = "GnBu") +
        scale_y_continuous(breaks=cumsum(dat[[totals]]) - dat[[totals]] / 2, labels=paste(dat[[by]], ":", dat[[totals]]))    
    }
    
    AA = ggpie(alloc, by = "ltr", totals = "wght") +
      ggtitle("Letter weights")
    
    AA
    

    The resulting pie chart:Pie

    Is there any way to generate something like this, for example:

    CoolPie

    Update for suggested dup - I think that thread is more about alternatives to pie charts and why pie charts are bad. I would like to stick to pie charts and want to find a solution to handling labels correctly/user-friendly.

  • AK88
    AK88 about 7 years
    Appreciate your response. Can you show any pie charts produced using plotly that give user-friendly labels?
  • timfaber
    timfaber about 7 years
    Check out the styled pie chart example in this reference: plot.ly/r/pie-charts Here you can set both labels/colors as well as define the label position.
  • AK88
    AK88 about 7 years
    Well, it partially accomplishes what I am after. Let's say that pieces of the pie are really slim and multiple labels should be located outside the slice-area. Like in the example I provided above. Is plotly good at this?
  • timfaber
    timfaber about 7 years
    Hm not really sure, I believe labels are dodged whenever they overlap so it should cover this in case of superslim labels. There are annotate options in plotly that could deliver you the lines shown in your second example but I m afraid that would cost a lot of custom work.
  • timfaber
    timfaber about 7 years
    Ha, I tried replacing ltr with ltr = 1:150 to give this a go, rerunning the script gives you a pretty amazing pie but not sure if it's very readable
  • AK88
    AK88 about 7 years
    Alright, thanks. Will take a look at plotly after the weekend.
  • AK88
    AK88 about 7 years
    Yes, that's the issue. I potentially will have around 30 pieces.
  • AK88
    AK88 about 7 years
    Accepted. There doesn't seem to be a better alternative. Thank you.
  • sar
    sar over 4 years
    This great, but I find the labels disappear off the top of the figure when I have a plot with small groups (eg. a=94, b=3, c=2, d=2). @timfaber

Related