Search code examples
rggplot2labelpositiongeom-text

ggplot: How to set different alignments on the geom_text position based on type of variable?


I have a 100% stacked bar chart that displays 3 types of variable. I've set a example db so I could create a graph more easily.

I've already adjust the chart with the colors and information I need. But I'm not being able to independently position the labels. Here's the current code and output.

Code:

(empilhado<-ggplot(dfm, aes(y = Year, x = abs(value), fill = variable)) + 
  scale_x_continuous(sec.axis = sec_axis(trans = ~.*1, name="Trab."), expand=expansion(mult=c(0,0.05)))+
  geom_col(data = rotulo, aes(y = Year, x=abs(trabalho), fill=NULL), width = .7, colour="black", lwd=0.1, position = "fill", orientation = "y") +
  geom_label(data = rotulo, aes(y= Year, x = abs(trabalho), fill=NULL, label=paste(format(round(trabalho, digits=0), nsmall=0, decimal.mark=",", big.mark="."), 
                                                                                  format(round(aprovado, digits=0), nsmall=0, decimal.mark=",", big.mark="."))
                              ), color="black", size=4, position = position_fill(vjust=1.06)) +
  geom_col(width = .7, colour="black", lwd=0.1, position = "fill", orientation = "y") +
  geom_text(aes(label=format(round(value, digits=0), nsmall=0, decimal.mark=",", big.mark=".")),
            size=4, color="white", position = position_fill(vjust=0.5)) +
  theme(panel.grid.major =   element_line(colour = "gray90",size=0.75), panel.grid.minor =   element_line(colour = "gray90",size=0.75),
        legend.position="top", axis.text.x = element_blank(), axis.ticks.x = element_blank(),
        axis.title.x = element_blank(), panel.background = element_blank())+
  scale_fill_manual(values = c("#000000","tomato","blue"))

Output:

Current Output

How is it now? Position_fill(vjust=0.5), so all the labels are centered inside its respective bar.

What I want? To be able to set the position of the 'Marionete' label on the left(like a vjust=0 would do), keep the 'Pedido' label as is (in the center of the 'Pedido' stacked bar) and place the 'Fatura' label on the right (like a vjust=1 would do).

Thanks in advance!


Solution

  • One option to achieve your desired result would be to compute/set the positions for each label and the horizontal alignment manually instead of making use of position="fill":

    Making use of some random mock data:

    library(ggplot2)
    library(dplyr)
    
    dfm <- dfm %>%
      group_by(Year) %>%
      arrange(desc(variable)) %>%
      mutate(
        pct = value / sum(value),
        x_label = case_when(
          variable == "Marionete" ~ 0,
          variable == "Pedido" ~ .5 * (cumsum(pct) + lag(cumsum(pct))),
          TRUE ~ 1
        ),
        hjust = case_when(
          variable == "Marionete" ~ 0,
          variable == "Pedido" ~ .5,
          TRUE ~ 1
        )
      )
    
    
    ggplot(dfm, aes(y = Year, x = abs(value), fill = variable)) +
      scale_x_continuous(sec.axis = sec_axis(trans = ~ . * 1, name = "Trab."), expand = expansion(mult = c(0, 0.05))) +
      geom_col(width = .7, colour = "black", lwd = 0.1, position = "fill", orientation = "y") +
      geom_text(aes(x = x_label, label = format(round(value, digits = 0), nsmall = 0, decimal.mark = ",", big.mark = "."), hjust = hjust),
        size = 4, color = "white"
      ) +
      theme(
        panel.grid.major = element_line(colour = "gray90", size = 0.75), panel.grid.minor = element_line(colour = "gray90", size = 0.75),
        legend.position = "top", axis.text.x = element_blank(), axis.ticks.x = element_blank(),
        axis.title.x = element_blank(), panel.background = element_blank()
      ) +
      scale_fill_manual(values = c("#000000", "tomato", "blue"))
    

    DATA

    set.seed(123)
    
    dfm <- data.frame(
      Year = rep(c(2006:2016), each = 3),
      value = sample(1:100, 3 * 11, replace = TRUE),
      variable = c("Fatura", "Pedido", "Marionete")
    )
    dfm$variable <- factor(dfm$variable, levels = c("Fatura", "Pedido", "Marionete"))
    dfm$Year <- factor(dfm$Year)