cmirian
cmirian

Reputation: 2253

ggplot: geom_text does not center-align above geom_col()

Please find my data p below. I had to include 100 samples to reproduce the error.

Question: why is geom_text not printing consistently center-aligned above the geom_col - e.g. 21 and 28 in All in the right SSA-facet? I tried adjusting position.dodge2 and vjust, but that did not work.

This thread addressed the issue but did not solve my problem.

enter image description here

My script

  ggplot(p %>%
           mutate(nystudie=as.character(study),          
                  best.resp =as.factor(response)) %>%       
           group_by(nystudie,best.resp) %>%      
           summarise(N=n(),Val=unique(treatment)) %>%    
           bind_rows(p %>% filter(response %in% 1:4, treatment!="Control") %>% droplevels() %>%       
                       mutate(nystudie=as.character(study),              
                              best.resp =as.factor(response)) %>%        
                       group_by(best.resp,treatment) %>% summarise(N=n()) %>%       
                       mutate(nystudie="All") %>%       
                       rename(Val=treatment)),
         aes(nystudie, N, color = best.resp, fill= best.resp)) +   
    geom_col(position = position_dodge2(preserve = "single", padding = 0.1)) +   
    facet_wrap(~Val,ncol = 2, scales="free") +
    scale_fill_grey(name="") +
    scale_color_grey(name="") +
    scale_y_continuous(breaks = seq(0,120,20)) +
    geom_text(aes(label=N),position = position_dodge2(.5), vjust=0, fontface=2, cex=4.5, show.legend = F) +
    theme(strip.background = element_blank(),
          strip.text = element_text(color = "black", size = 15),
          axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1),
          plot.margin = unit(c(1,3,1,1), "lines"))

Data

p <- structure(list(study = structure(c(8L, 12L, 12L, 12L, 4L, 4L, 
1L, 11L, 11L, 13L, 1L, 13L, 14L, 9L, 9L, 10L, 12L, 11L, 4L, 11L, 
11L, 12L, 8L, 11L, 13L, 11L, 6L, 15L, 6L, 4L, 7L, 13L, 11L, 4L, 
1L, 6L, 1L, 11L, 16L, 1L, 10L, 15L, 1L, 11L, 1L, 6L, 1L, 11L, 
12L, 11L, 13L, 16L, 1L, 8L, 11L, 10L, 4L, 4L, 12L, 10L, 6L, 15L, 
12L, 14L, 12L, 1L, 1L, 16L, 12L, 12L, 8L, 7L, 1L, 1L, 13L, 13L, 
14L, 9L, 14L, 2L, 11L, 4L, 1L, 16L, 15L, 11L, 9L, 4L, 13L, 12L, 
6L, 16L, 4L, 1L, 15L, 6L, 4L, 1L, 9L, 2L), .Label = c("1", "2", 
"3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", 
"15", "22"), class = "factor"), response = c("1", "3", "4", "4", 
"3", "3", "3", "4", "4", "4", "4", "4", "3", "4", "4", "4", "3", 
"4", "4", "4", "4", "3", "1", "4", "4", "4", "3", "4", "3", "3", 
"4", "4", "4", "3", "4", "4", "4", "4", "4", "3", "4", "4", "3", 
"4", "4", "3", "3", "4", "3", "4", "4", "4", "4", "3", "3", "4", 
"4", "3", "3", "4", "3", "4", "4", "4", "3", "3", "4", "4", "4", 
"4", "2", "4", "4", "4", "4", "4", "3", "4", "3", "3", "4", "4", 
"4", "4", "4", "4", "3", "3", "4", "4", "3", "4", "4", "4", "4", 
"3", "3", "4", "2", "3"), treatment = structure(c(2L, 2L, 2L, 
2L, 1L, 1L, 1L, 2L, 2L, 2L, 1L, 2L, 2L, 2L, 2L, 1L, 2L, 2L, 1L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 1L, 2L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 
1L, 1L, 2L, 1L, 1L, 1L, 2L, 1L, 2L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 
1L, 1L, 2L, 2L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 2L, 2L, 2L, 1L, 1L, 
1L, 2L, 2L, 2L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 1L, 2L, 1L, 1L, 
1L, 2L, 2L, 2L, 1L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 2L, 
1L), .Label = c("SSTR", "SSA"), class = "factor")), row.names = c(NA, 
-100L), class = "data.frame")

Upvotes: 2

Views: 1103

Answers (1)

stefan
stefan

Reputation: 124393

When adding labels you have to take care to use the same positioning as for geom_col. To align the labels with the bars use position_dodge2(preserve = "single", width = .9, padding = 0.1):

library(ggplot2)
library(dplyr)

d1 <- p %>%
  mutate(
    nystudie = as.character(study),
    best.resp = as.factor(response)
  ) %>%
  group_by(nystudie, best.resp) %>%
  summarise(N = n(), Val = unique(treatment))
#> `summarise()` regrouping output by 'nystudie' (override with `.groups` argument)

d2 <- p %>%
  filter(response %in% 1:4, treatment != "Control") %>%
  droplevels() %>%
  mutate(
    nystudie = as.character(study),
    best.resp = as.factor(response)
  ) %>%
  group_by(best.resp, treatment) %>%
  summarise(N = n()) %>%
  mutate(nystudie = "All") %>%
  rename(Val = treatment)
#> `summarise()` regrouping output by 'best.resp' (override with `.groups` argument)

d <- bind_rows(d1, d2)

ggplot(d, aes(nystudie, N, color = best.resp, fill = best.resp)) +
  geom_col(position = position_dodge2(preserve = "single", padding = 0.1)) +
  facet_wrap(~Val, ncol = 2, scales = "free") +
  scale_fill_grey(name = "") +
  scale_color_grey(name = "") +
  scale_y_continuous(breaks = seq(0, 120, 20)) +
  geom_text(aes(label = N), position = position_dodge2(preserve = "single", width = .9, padding = 0.1), vjust = 0, fontface = 2, cex = 4.5, show.legend = F) +
  theme(
    strip.background = element_blank(),
    strip.text = element_text(color = "black", size = 15),
    axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1),
    plot.margin = unit(c(1, 3, 1, 1), "lines")
  )

Upvotes: 2

Related Questions