1
votes


I'm working with ggplot2, stacked barplot to 100% with relative values, using the position = "fill" option in geom_bar().
Here my code:

test <- data.frame (x = c('a','a','a','b','b','b','b')
        ,k = c('k','j','j','j','j','k','k')
        ,y = c(1,3,4,2,5,9,7))

plot <- ggplot(test, aes(x =x, y = y, fill = k)) 
plot <- plot + geom_bar(position = "fill",stat = "identity") 
plot <- plot +  scale_fill_manual(values = c("#99ccff", "#ff6666"))
plot <- plot  + geom_hline(yintercept = 0.50)+ggtitle("test")
plot

Here the result:

enter image description here

However, I need to add the labels on the various bars, also on the "sub bars". To do this, I worked with the geom_text():

plot  + geom_text(aes(label=y, size=4))

But the result is not good. I tried without luck the hjust and vjust parameters, and also using something like:

plot  + geom_text(aes(label=y/sum(y), size=4))

But I did not reach the result needed (I'm not adding all the tests to not overload the question with useless images, if needed, please ask!).
Any idea about to have some nice centered labels?

1

1 Answers

2
votes

label specifies what to show, and y specifies where to show. Since you are using proportions for y-axis with position = "fill", you need to calculate the label positions (geom_text(aes(y = ...))) in terms of proportions for each x using cumulative sums. Additionally, to display only the total proportion of a given color, you will need to extract the Nth row for each x, k combination. Here, I am building a separate test_labels dataset for use in geom_text to display the custom labels:

test <- data.frame (x = c('a','a','a','b','b','b','b'),
                    k = c('k','j','j','j','j','k','k'),
                    y = c(1,3,4,2,5,9,7))

test_labels = test %>%
  arrange(x, desc(k)) %>%
  group_by(x) %>%
  mutate(ylabel_pos = cumsum(y)/sum(y),
         ylabel = y/sum(y)) %>%
  group_by(k, add = TRUE) %>%
  mutate(ylabel = sum(ylabel)) %>%
  slice(n())

 ggplot(test, aes(x =x, y = y, fill = k)) +
  geom_bar(position = "fill", stat = "identity") +
  scale_fill_manual(values = c("#99ccff", "#ff6666")) +
  geom_hline(yintercept = 0.50) + 
  geom_text(data = test_labels, 
            aes(y = ylabel_pos, label=paste(round(ylabel*100,1),"%")), 
            vjust=1.6, color="white", size=3.5) +
  ggtitle("test")

Result:

> test_labels
# A tibble: 4 x 5
# Groups:   x, k [4]
       x      k     y ylabel_pos    ylabel
  <fctr> <fctr> <dbl>      <dbl>     <dbl>
1      a      j     4  1.0000000 0.8750000
2      a      k     1  0.1250000 0.1250000
3      b      j     5  1.0000000 0.3043478
4      b      k     7  0.6956522 0.6956522

enter image description here