6

Background: I am new to R and ggplot2 and hope to get a simple answer that benefits others in the same situation.

Question: What is a simple way in ggplot2 to make each bar add up to 100% and displaying percentage labels inside each bar?

Goal: What I want it to look like (each column totals 100%, with percentage labels inside each column).

Current Chart: This is the bar chart I have so far; based on the "mtcars" dataset (What it currently looks like). Below I have for the "Current Chart":

library(ggplot2) # loads ggplot2
data <- mtcars # gets the mtcars dataset

#INFO: A simple barchart with X-axis being Nr of Cylinders, fill color indicating whether or not the car model has an Automatic gearbox..
# ..and Y-axis showing the count of cars by Nr of Cylinders
ggplot(mtcars, aes(x=cyl, fill = factor(am))) +
  geom_bar() +
  stat_count(geom = "text", 
             aes(label = paste(round((..count..)/sum(..count..)*100), "%")), # This row calculates the percentage across all data, adding up to 100%, but I want it to add up to 100% per X-variable (Nr of Cylinders = 4, 6, 8)
             position=position_stack(vjust=0.5), colour="white") # This row positions the bar percentage level and colors it white.

Many thanks in advance!

Daniel
  • 83
  • 1
  • 1
  • 10
  • Might be a duplicate of https://stackoverflow.com/questions/9563368/create-stacked-barplot-where-each-stack-is-scaled-to-sum-to-100 – gcourtet Jul 12 '18 at 12:19
  • I think the difference is that I am trying to _add the percentage labels within each chart_ as well. – Daniel Jul 12 '18 at 12:44
  • For the percentages this might be what you are looking for: https://stackoverflow.com/questions/44724580/in-rs-ggplot2-how-to-add-percentage-labels-to-a-stacked-barplot-with-percenta – gcourtet Jul 12 '18 at 12:47

4 Answers4

7
library(ggplot2) # loads ggplot2
data <- mtcars 

ggplot(mtcars, aes(x=cyl, fill = factor(am))) +
  geom_bar(position = "fill") +
  stat_count(geom = "text", 
             aes(label = paste(round((..count..)/sum(..count..)*100), "%")),
             position=position_fill(vjust=0.5), colour="white")

Your code was almost there, just needed _fill instead of _stack in position.

enter image description here

RLave
  • 8,144
  • 3
  • 21
  • 37
  • Almost! Do you know how to make each bar percentage total up to 100%? Example: Currently the leftmost bar is showing 9% and 25% which adds up to a 34% of the plot percent total. Instead I would like that bar to show 26%, 74% with a bar total of 100%. – Daniel Jul 12 '18 at 20:46
  • Oh I see, I think that you need to get them first, out of the ggplot call, say on a different dataframe, then call it inside the `geom_text` – RLave Jul 13 '18 at 13:27
  • I've tried a solution with either `stat_count` or `geom_text` with no success, it seems that you can't group by within this functions.. – RLave Jul 13 '18 at 13:28
5

I know it's late but posting this because I often look for this too... you needed:

    # Get labels
    percentData <- mtcars  %>% group_by(cyl) %>% count(am) %>%
    mutate(ratio=scales::percent(n/sum(n)))

to calculate the proportions within each bar and then to plot:

    # Plot
    ggplot(mtcars,aes(x=factor(cyl),fill=factor(am)))+
    geom_bar(position="fill")+
    geom_text(data=percentData, aes(y=n,label=ratio), 
    position=position_fill(vjust=0.5))
Shamee
  • 65
  • 1
  • 3
4
ggplot(mtcars, aes(x=factor(cyl), fill = factor(am))) +
  geom_bar(position = "fill")
Lennyy
  • 5,932
  • 2
  • 10
  • 23
  • Is it possible to add the Bar Percentages within each bar (as in the "Goal" picture attached in the question)? – Daniel Jul 12 '18 at 12:31
1

Just to add to RLave response:

You can change the axis to show numbers as percentage instead of proportions using the scales package:

library(scales) # <- includes scales library
library(ggplot2)
data <- mtcars 

ggplot(mtcars, aes(x=cyl, fill = factor(am))) +
  geom_bar(position = "fill") +
  stat_count(geom = "text", 
             aes(label = paste(round((..count..)/sum(..count..)*100), "%")),
             position=position_fill(vjust=0.5), colour="white") +
  scale_y_continuous(labels = percent) #          <- set the desired formatting