Home > Blockchain >  How to use position_dodge with preserve = 'single' in geom_text?
How to use position_dodge with preserve = 'single' in geom_text?

Time:01-20

I'm trying to label the bars with geom_text. It works in most cases with position_dodge, but for some cases I get plots that look like this. I use preserve = 'single' to get around the wide bars, but the respective geom_text does not move to match the bar. I've made it work with position_dodge2() but I like how the bars are aligned in position_dodge all the way to the left in this case.

ggplot(mtcars, aes(factor(cyl), fill = factor(vs)))   
    geom_bar(aes(y = ..count..), stat = 'count', position = position_dodge(preserve = 'single'))   
    geom_text(aes(label = ..count..), stat = 'count', position = position_dodge(width = 1))  

enter image description here

The "14" on factor 8 is aligned to the middle instead of to the left. Is there a simple fix to this?

If I switch to position_dodge2 and use preserve = 'single' it works, but the bar is centered on the x axis. In position_dodge the bar is left aligned and the missing value is right aligned. If there is a way to use position_dodge2 without sacrificing alignment that would work as well.

enter image description here

CodePudding user response:

I don't love this, but one possibility is to enumerate the possibilities with tidyr::complete so that any missing ones get an NA, which will plot with the spacing you want:

library(tidyverse)
mtcars %>%
  count(cyl = factor(cyl), vs = factor(vs)) %>%
  complete(cyl, vs) %>%   # creates "8 cyl / 1 vs / NA n" row
  ggplot(aes(cyl, n, fill = vs))  
  geom_col(position = position_dodge(preserve = 'single'))  
  geom_text(aes(label = n), position = position_dodge(width = 1))

enter image description here

CodePudding user response:

You could do it manually like this:

ggplot(mtcars, aes(cyl, fill = factor(vs)))   
  geom_bar(aes(y = ..count..), stat = 'count', position = position_dodge(preserve = 'single'))   
    # geom_text(aes(label = ..count..), stat = 'count', position = position_dodge(width = 1))  
  geom_text(aes(x=5.5, label="4.5", y=4), colour="#376795", text=element_text(size=11))  
  geom_text(aes(x=6.5, label="4", y=5), colour="#376795", text=element_text(size=11))  
  geom_text(aes(x=3.5, label="1", y=3), colour="#376795", text=element_text(size=11))  
  geom_text(aes(x=4.5, label="10", y=11), colour="#376795", text=element_text(size=11))  
  geom_text(aes(x=7.5, label="14", y=15), colour="#376795", text=element_text(size=11)) 

But you would have to leave the cyl as a double. This is not like an efficient method that is generalizable but it gets the job done for this ask.

enter image description here

  •  Tags:  
  • Related