Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In geom_text, can "labels=scales::percent" be rounded?

Tags:

r

ggplot2

I'm making a series of bar charts where the percent value is placed above each bar. I'd like to round this to 0 decimal places, but it defaults to 1 decimal place. Here's an example using mtcars.

library(ggplot2)
library(scales)

d <- mtcars

g <- ggplot(d, aes(gear)) +
geom_bar(aes(y = (..count..)/sum(..count..), fill=factor(..x..)), stat= "count")+
geom_text(aes(label = scales::percent((..count..)/sum(..count..)),
            y= ((..count..)/sum(..count..))), stat="count",
        vjust = -.25)

This gives you:enter image description here

Is there a way to round these to the nearest whole number, so that the bars are labeled 47%, 38%, and 16%?

Work-arounds could include annotating the labels manually or generating a summarized data.frame from which to pull the labels. However, since I'm generating numerous tables, I'd much prefer to include all of my code within the single ggplot command.

like image 327
John J. Avatar asked Dec 14 '16 17:12

John J.


2 Answers

Here is a minimal change to your current code that will do what you want:

library(ggplot2)
library(scales)

d <- mtcars

g <- ggplot(d, aes(gear)) +
geom_bar(aes(y = (..count..)/sum(..count..), fill=factor(..x..)), stat= "count")+
geom_text(aes(label = scales::percent(round((..count..)/sum(..count..),2)),
            y= ((..count..)/sum(..count..))), stat="count",
        vjust = -.25)

I have added a call to round(...,2) in your division that will round the ratio before passing it to percent.


Personally, I would do this outside of ggplot for clarity of code.

library(ggplot2)
library(scales)
library(dplyr)

d <- mtcars %>%
  group_by(gear) %>%
  summarise(Count = n()) %>%
  mutate( gear = factor(gear),
    Ratio = Count / sum(Count),
         label = percent(Ratio %>% round(2)))

g <- ggplot(d, aes(x=gear,y=Ratio,label=label,fill=gear)) +
  geom_bar(stat='identity') +
  geom_text(vjust=0)
g

When I have to go back and look at that in 6 months, it will be a lot easier to figure out what I did.

like image 198
Bishops_Guest Avatar answered Sep 20 '22 16:09

Bishops_Guest


I dealt with the same problem and solved it by adding accuracy = 1L in scales::percent() and it worked perfectly:

label = scales::percent(round((..count..)/tapply(..count..,..PANEL..,sum)[..PANEL..], 
                              2), 
                        accuracy = 1L))
like image 33
Benjamin Telkamp Avatar answered Sep 19 '22 16:09

Benjamin Telkamp