Search code examples
rggplot2heatmapaxis-labelsfacet-grid

Alignment of y axis labels in faced_grid and ggplot?


By using ggplot and faced_grid functions I'm trying to make a heatmap. I have a categorical y axis, and I want y axis labels to be left aligned. When I use theme(axis.text.y.left = element_text(hjust = 0)), each panels' labels are aligned independently. Here is the code:

#data
set.seed(1)
gruplar <- NA
for(i in 1:20) gruplar[i] <- paste(LETTERS[sample(c(1:20),sample(c(1:20),1),replace = T) ],
                                   sep="",collapse = "")

gruplar <- cbind(gruplar,anagruplar=rep(1:4,each=5))
tarih <- data.frame(yil= rep(2014:2019,each=12) ,ay =rep_len(1:12, length.out = 72))

gruplar <- gruplar[rep(1:nrow(gruplar),each=nrow(tarih)),]
tarih <- tarih[rep_len(1:nrow(tarih),length.out = nrow(gruplar)),]

grouped <- cbind(tarih,gruplar)
grouped$value <- rnorm(nrow(grouped))

#plot
p <- ggplot(grouped,aes(ay,gruplar,fill=value))
p <- p + facet_grid(anagruplar~yil,scales = "free",
                    space = "free",switch = "y") 
p <- p + theme_minimal(base_size = 14) +labs(x="",y="") + 
  theme(strip.placement = "outside",
        strip.text.y = element_text(angle = 90))
p <- p + geom_raster(aes(fill = value), na.rm = T)
p + theme(axis.text.y.left = element_text(hjust = 0, size=14))

I know that by putting spaces and using a mono-space font I can solve the problem, but I have to use the font 'Calibri Light'.


Solution

  • Digging into grobs isn't my favourite hack, but it can serve its purpose here:

    # generate plot
    # (I used a smaller base_size because my computer screen is small)
    p <- ggplot(grouped,aes(ay,gruplar,fill=value)) + 
      geom_raster(aes(fill = value),na.rm = T) + 
      facet_grid(anagruplar~yil,scales = "free",space = "free",switch = "y") + 
      labs(x="", y="") +
      theme_minimal(base_size = 10) +
      theme(strip.placement = "outside",
            strip.text.y = element_text(angle = 90),
            axis.text.y.left = element_text(hjust = 0, size=10))
    
    # examine ggplot object: alignment is off
    p 
    
    # convert to grob object: alignment is unchanged (i.e. still off)
    gp <- ggplotGrob(p)
    dev.off(); grid::grid.draw(gp)
    
    # change viewport parameters for left axis grobs
    for(i in which(grepl("axis-l", gp$layout$name))){
      gp$grobs[[i]]$vp$x <- unit(0, "npc")     # originally 1npc
      gp$grobs[[i]]$vp$valid.just <- c(0, 0.5) # originally c(1, 0.5)
    }
    
    # re-examine grob object: alignment has been corrected
    dev.off(); grid::grid.draw(gp)
    

    plot