3

I'm trying to add percentage labels in a stacked bar chart. What can I add to my geom_bar to show the percentage labels inside stacked bars?

This is my data:

myresults=data.frame(
    manipulation=rep(c(-20,-10,0,10,20,-20,-10,0,10,20,-20,-10,0,10,20)),
    variable=rep(c("a","a","a","a","a","f","f","f","f","f","l","l","l","l","l")),
    value=c(73,83,76,75,78,261,301,344,451,599,866,816,780,674,523))

This is my bar chart, without percentage labels.

I have little knowledge in this. I googled "gglot stacked bar percentage label" and found that adding percentage labels could be done with "+ geom_text(stat="count")".

But when I added + geom_text(stat="count") to my ggplot geom_bar, R said "Error: stat_count() must not be used with a y aesthetic." I tried to figure out what a y aesthetic is, but it hasn't been very successful.

This is what I did:

mydata <- ggplot(myresults, aes(x=manipulation, y=value, fill=variable))

mydata + geom_bar(stat="identity", position="fill", colour="black") + scale_fill_grey() + scale_y_continuous(labels=scales::percent) + theme_bw(base_family="Cambria") + labs(x="Manipulation", y=NULL, fill="Result") + theme(legend.direction="vertical", legend.position="right")
Hyeonjeong
  • 31
  • 1
  • 5
  • 1
    Welcome to SO. I flagged your question as a duplicate to help you - the question should be able to help you hopefully. If you feel it doesn't answer your question, change your question and let me know. – tjebo Nov 07 '19 at 08:20
  • @Tjebo Thanks for reading and taking the time to comment! But the question and asnwer you linked for me was the google result I got, which made me try "+ geom_text(stat="count")". I'd like to know what went wrong in my case. – Hyeonjeong Nov 07 '19 at 08:35

2 Answers2

6

You can do something similar to the accepted answer in: Adding percentage labels to a bar chart in ggplot2. The main difference is that your values are piled up( "stacked") whereas in that example it is side by side ("dodged")

Make a column of percentages:

myresults_pct <- myresults %>% 
group_by(manipulation) %>% 
mutate(pct=prop.table(value))

Now we plot this:

    ggplot(myresults_pct, 
aes(x=manipulation, y=pct,fill=variable)) + 
geom_col()+
scale_fill_grey()+
geom_text(aes(label = scales::percent(pct)),
position="stack",vjust=+2.1,col="firebrick",size=3)+
scale_y_continuous(label = scales::percent)

The important parameters in geom_text is position="stacked", and play around with vjust, to move up or down your label. (I apologize in advance for the awful text color..).

enter image description here

StupidWolf
  • 45,075
  • 17
  • 40
  • 72
  • you're welcome! I encourage you to provide data using dput, it's part of asking a good question so that others can help and learn too :) – StupidWolf Nov 10 '19 at 13:13
  • Thanks! I edited my question to add the data I used, but my data frame was originally made from a very big excel file, by doing dcast(myresults, manipulation ~ result) and then melt(myresults, id.vars="manipulation"). Making this comment, I suddenly noticed something I didn't realize 5 hours ago. Can I ask a follow up question? It seems like I do need position="fill", because when I removed it, geom_text worked, but my y axis became 125 000%, 100 000%, 75 000%, 50 000%, 25 000%, 0% instead of the originall 100~0%. What can I do if I want to keep position="fill" and still add the labels? – Hyeonjeong Nov 10 '19 at 17:37
  • Thanks for the dput, I can change my post above according to what you provide – StupidWolf Nov 10 '19 at 18:07
  • Done @Hyeonjeong, please provide the data next time, and yeah you don't need position = "fill", it's really odd. – StupidWolf Nov 10 '19 at 18:25
  • Hi @Hyeonjeong does it work? – StupidWolf Nov 11 '19 at 11:04
1

You can try tu create the position of geom text and put it on the bars:

mydata[, label_ypos := cumsum(value), by = manipulation]

ggplot(myresults, aes(x=manipulation, y=value, fill=variable)) + 
geom_bar(stat="identity", position="fill", colour="black") +
geom_text(aes(y=label_ypos, label= paste(round(rent, 2), '%')), vjust=2, 
        color="white", size=3.5) +
scale_y_continuous(labels = scales::percent) +
labs(x = "Manipulation", y=NULL, fill="Result") +
theme_bw(base_family = "Cambria") +
theme(legend.direction = "vertical", legend.position = "right") +
scale_fill_grey() 
K. Peltzer
  • 326
  • 3
  • 7
  • Thank you for asnwering! StupidWolf's answer solved my problem but I got an unexpected additional help from your answer (specifically the "color="white", size=3.5" part), which made my bar chart prettier. – Hyeonjeong Nov 10 '19 at 12:05