1

I have made a chart with the following data:

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

mydf <- tibble(type = c(rep(c(rep("TypeA", 4), rep("TypeB", 4)), 2)),
               Ratings = rep(c("Top", "Middle", "Low", "NA"), 4),
               Prop = c(0.62, 0.15, 0.15, 0, 0.32, 0.16, 0.47, 0, 0.38, 0.31, 0.31, 0, 0.16, 0.16, 0.63, 0.05),
               Question = c(rep("Question1", 8), rep("Question2", 8)))
mydf$Ratings <- factor(mydf$Ratings) %>% fct_inorder() %>% fct_rev()

And here's my code to make the chart:

mydf %>% filter(Prop > 0) %>% ggplot(aes(x = Question, y = Prop, fill = Ratings)) + 
geom_bar(position = "fill", stat = "identity") + 
geom_text(aes(label = percent(round(Prop,2))), position = position_stack(vjust = 0.5)) + 
facet_grid(~ type) + scale_y_continuous(labels = percent) + 
guides(fill = guide_legend(reverse = TRUE))

It produced the following chart. I specifically used position = position_stack(vjust = 0.5) to center the labels halfway through the bars. It clearly doesn't look right for the labels for Question1. Is this a bug? Have I set my data up incorrectly?

enter image description here

Community
  • 1
  • 1
Phil
  • 7,287
  • 3
  • 36
  • 66
  • You need to create another variable that defines the height for the label, see [here](https://www.getdatajoy.com/examples/r-plots/stacked-bar-graph) for more details. – figurine Dec 09 '16 at 23:25
  • As per [this answer](http://stackoverflow.com/a/6645506/5221626), this is no longer needed for ggplot2 v2.2. – Phil Dec 09 '16 at 23:36

1 Answers1

1

You have position="fill" for geom_bar, but position_stack for geom_text. As a result, the top of the geom_bar stack is always 100%, but the top of the geom_text stack is whatever the sum of the values in that stack happens to be. The sums of the values for TypeA Question1 and TypeB Question1 are both less than 100%, so the height of the label stack is lower than the height of the bar stack.

For the label heights to match the bar heights, change to position_fill in geom_text. (Note, however, that since the percentages don't add up to 100% for two of the four bar stacks, using position_fill() is misleading if you don't also normalize the labels to add to 100% in each stack.)

I've also removed the last line reversing the legend so that the legend will be in the same color order as the bar sections:

mydf %>% filter(Prop > 0) %>% 
  ggplot(aes(x = Question, y = Prop, fill = Ratings)) + 
  geom_bar(position="fill", stat="identity") + 
  geom_text(aes(label = percent(round(Prop,2))), position=position_fill(vjust = 0.5)) + 
  facet_grid(~ type) + 
  scale_y_continuous(labels = percent) 

enter image description here

eipi10
  • 91,525
  • 24
  • 209
  • 285