3

I have data that I need to put into a stack bar chart but when I add the labels of the counts some of the labels are above the category and some are under the category. I tried modifying position arguments of the geom_text function to no avail.

Below is a reproducible example showing the labels for the 'Under' category seating above that category and the labels of the 'Over' category seating inside the bar.

library(tidyverse)

data.frame(AgeGroup = sample(c(rep("Over",10),"Under"), 6000, replace = TRUE),
DueDate = sample( 
         seq( as.Date("2015-01-01"), 
              as.Date("2015-06-30"), by="1 month") ,  
         6000,replace = TRUE),
             stringsAsFactors = TRUE) %>%
group_by(AgeGroup,DueDate) %>%
  tally() %>% ungroup %>% 
  ggplot() +
  geom_bar(aes(x=DueDate, y=n, fill = AgeGroup),stat = "identity") +
  geom_text(aes(x=DueDate, y=n
            ,label = prettyNum(n,big.mark = ","))
        , vjust = 0,  size = 2) +
  scale_y_continuous(labels = scales::comma) +
  theme_bw() +
  labs(title="Where are the labels")

Below is the output chart. enter image description here

user3357059
  • 1,122
  • 1
  • 15
  • 30
  • 1
    Just to note: data derived using `sample` is not strictly reproducible unless you use `set.seed()` first. – neilfws Sep 20 '18 at 23:52

2 Answers2

6

Just use n/2 as the y position for geom_text(), and it will always fall "inside" the bar:

library(tidyverse)

data.frame(AgeGroup = sample(c(rep("Over",10),"Under"), 6000, replace = TRUE),
           DueDate = sample( 
               seq( as.Date("2015-01-01"), 
                    as.Date("2015-06-30"), by="1 month") ,  
               6000,replace = TRUE),
           stringsAsFactors = TRUE) %>%
    group_by(AgeGroup,DueDate) %>%
    tally() %>% ungroup %>% 
    ggplot() +
    geom_bar(aes(x=DueDate, y=n, fill = AgeGroup),stat = "identity") +
    geom_text(aes(x=DueDate, y=n/2
                  ,label = prettyNum(n,big.mark = ","))
              , vjust = 0,  size = 2) +
    scale_y_continuous(labels = scales::comma) +
    theme_bw() +
    labs(title="Where are the labels")

enter image description here

EDIT: That quick solution will only work for your specific example. If you have more than two categories per bar, or if the values are more evenly distributed, it will not fly. i.e.:

set.seed(999)
data.frame(Direction = sample(rep(c("South", "West", "East", "North")), 6000, replace = TRUE),
           DueDate = sample( 
               seq( as.Date("2015-01-01"), 
                    as.Date("2015-06-30"), by="1 month") ,  
               6000,replace = TRUE),
           stringsAsFactors = TRUE) %>%
    group_by(Direction, DueDate) %>%
    tally() %>% 
    ungroup %>%
    arrange(desc(Direction)) %>% 
    group_by(DueDate) %>% 
    mutate(pos = cumsum(n) - n/2) %>% 
    ggplot() +
    geom_bar(aes(x=DueDate, y=n, fill = Direction),stat = "identity") +
    geom_text(aes(x=DueDate, y=pos, label = prettyNum(n,big.mark = ","))
              , vjust = 0,  size = 2) +
    scale_y_continuous(labels = scales::comma) +
    theme_bw() +
    labs(title="Where are the labels")

enter image description here

So here's a general solution, that adds a "position" column to the dataframe (arrange(desc(Direction)) %>% group_by(DueDate) %>% mutate(pos = cumsum(n) - n/2)), to use with geom_text() and place the labels exactly where they belong:

set.seed(999)
data.frame(Direction = sample(rep(c("South", "West", "East", "North")), 6000, replace = TRUE),
           DueDate = sample( 
               seq( as.Date("2015-01-01"), 
                    as.Date("2015-06-30"), by="1 month") ,  
               6000,replace = TRUE),
           stringsAsFactors = TRUE) %>%
    group_by(Direction, DueDate) %>%
    tally() %>% 
    ungroup %>%
    arrange(desc(Direction)) %>% 
    group_by(DueDate) %>% 
    mutate(pos = cumsum(n) - n/2) %>% 
    ggplot() +
    geom_bar(aes(x=DueDate, y=n, fill = Direction),stat = "identity") +
    geom_text(aes(x=DueDate, y=pos, label = prettyNum(n,big.mark = ","))
              , vjust = 0,  size = 2) +
    scale_y_continuous(labels = scales::comma) +
    theme_bw() +
    labs(title="Where are the labels")

enter image description here

HAVB
  • 1,858
  • 1
  • 22
  • 37
1

You can try:

geom_text(aes(label = n), position = position_stack(vjust = 0.5)
Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
bodega18
  • 596
  • 2
  • 13