Skip to content

Instantly share code, notes, and snippets.

@jsonbecker
Created December 1, 2016 04:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jsonbecker/0cc702804512fdf29c7f9067adfc17d0 to your computer and use it in GitHub Desktop.
Save jsonbecker/0cc702804512fdf29c7f9067adfc17d0 to your computer and use it in GitHub Desktop.
How do I get labels on this plot?
library(ggplot2)
df <- data.frame(type = c(rep('Elementary', 2), rep('Middle', 2), rep('High', 2)),
included = rep(c('included','excluded'),3),
dollars = c(1000, 2500, 4000, 1000, 3000, 2800))
ggplot(data = df, aes(type, dollars, fill = included)) +
geom_bar(position = 'fill', stat = 'identity') +
geom_text()
@jsonbecker
Copy link
Author

Note: remove geom_text() and it makes the right graph. But geom_text wants a label, and doesn't like dollars or y which are my best guesses as to what should go there.

@noamross
Copy link

noamross commented Dec 1, 2016

Not sure exactly what your desired output is, but this is a start:

library(ggplot2)

df <- data.frame(type = c(rep('Elementary', 2), rep('Middle', 2), rep('High', 2)),
                 included = rep(c('included','excluded'),3),
                 dollars = c(1000, 2500, 4000, 1000, 3000, 2800))
ggplot(data = df, aes(x=type, y=dollars, fill = included, label=type)) + 
  geom_bar(position = 'fill', stat = 'identity') +
  geom_text(position='fill')  

@joranE
Copy link

joranE commented Dec 1, 2016

...or make both position = "stack" if you want the bars to not be scaled to proportions. Either way it was the different default position settings bar/text.

@jsonbecker
Copy link
Author

@noamross So my issue is I want the percentages to be the labels, not the type. While your code works, it provides the wrong text and I can't set the "label" to the proportions seemingly produced by position = 'fill'

@joranE thanks, but the primary motivation was finding out after 6 years of using ggplot2 that position = 'fill' existed and I didn't have to use prop.table() like I used to.

@hadley
Copy link

hadley commented Dec 1, 2016

The closest you can get would be:

ggplot(data = df, aes(x=type, y=dollars, fill = included, label=type)) + 
  geom_bar(position = 'fill', stat = 'identity') +
  geom_text(position='fill', aes(label = ..y..))  

But you can't display the percentage that way because the filling happens after geom_text has been given the data.

It's not so hard to do with dplyr though:

library(ggplot2)
library(dplyr)

df <- data.frame(
  type = c(rep('Elementary', 2), rep('Middle', 2), rep('High', 2)),
  included = rep(c('included','excluded'),3),
  dollars = c(1000, 2500, 4000, 1000, 3000, 2800)
)

df %>% 
  group_by(type) %>% 
  mutate(prop = dollars / sum(dollars)) %>% 
  ggplot(aes(type, prop, fill = included)) + 
  geom_col() +
  geom_text(aes(label = scales::percent(prop)), position = position_stack(vjust = 0.5))  

Which has the additional advantage that you can easily check the computation.

@jsonbecker
Copy link
Author

@hadley thanks I really appreciate the response. The latter way with dplyr is generally how I've done this, but I was hoping my discovery of position = 'fill' meant I could remove that step. Oh well!

@cpsievert
Copy link

Another option is to leverage ggplotly()'s ability to return data after statistics have been applied:

https://cpsievert.github.io/plotly_book/extending-ggplotly.html#leveraging-statistical-output

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment