Rodaina Ahmed
Rodaina Ahmed

Reputation: 11

I want to add the count percentage for each category as a label to my ggplot pie chart

I am using the code:

age_pie_chart <- ggplot(data = data , aes(x = "", fill = `Q1: How old are you?`))+
  geom_bar(position = "fill", width = 1) + 
  coord_polar(theta = "y") + xlab("") + ylab("") +  blank_theme + scale_fill_grey()+
  theme(axis.text.x=element_blank())
age_pie_chart

I want the percentage of each category to be added inside the chart. from searching I understand that I need to use geom_text function but before that I need to construct a frequency table with the percentage of the count of each category.

this is the pie chart

Upvotes: 1

Views: 1339

Answers (1)

chemdork123
chemdork123

Reputation: 13863

Here's an example with some dummy data. First, here's the dummy data. I'm using sample() to select values and then I'm ensuring we have a "small" slice by adding only 2 values for Q1 = "-15".

set.seed(1234)
data <- data.frame(
  Q1 = c(sample(c('15-7','18-20','21-25'), 98, replace=TRUE), rep('-15', 2))
)

For the plot, it's basically the same as your plot, although you don't need the width argument for geom_bar().

To get the text positioned correctly, you'll want to use geom_text(). You could calculate the frequency before plotting, or you could have ggplot calculate that on the fly much like it did for geom_bar by using stat="count" for your geom_text() layer.

library(ggplot2)

ggplot(data=data, aes(x="", fill=Q1)) +
  geom_bar(position="fill") +
  geom_text(
    stat='count', 
    aes(y=after_stat(..count..),
        label=after_stat(scales::percent(..count../sum(..count..),1))),
    position=position_fill(0.5),
  ) +
  coord_polar(theta="y") +
  labs(x=NULL, y=NULL) +
  scale_fill_brewer(palette="Pastel1") +
  theme_void()

enter image description here

So to be clear what's going on in that geom_text() line:

  • I'm using stat="count". We want to access that counting statistic within the plot, so we need to specify to use that special stat function.

  • We are using ..count.. within the aesthetics. The key here is that in order to access the ..count.. value, we need the stat function to compute first. You can use the after_stat() function to specify that the stat function should happen first before mapping the aesthetics - that opens ..count.. up to use for use within aes()!

  • Percent calculation for the label. This happens via ..count../sum(..count..). I'm using scales::percent() as a way to format the label as a percent.

  • Position = fill. Like the bar geom, we are also needing to use position="fill". You need to specify to use the actual position_fill() method, since it allows us to access the vjust argument. This positions each text value in the "middle" of each slice. If you just set position="fill", you get the text positioned at the edge of each slice.

Upvotes: 2

Related Questions