Home > OS >  How to put y axis title in top left corner of graph using grid's functions?
How to put y axis title in top left corner of graph using grid's functions?

Time:09-17

I want to write the y-axis title horizontally on top of the y-axis line while keeping settings defined for the y-axis in the theme() function. The objective is to avoid wasting space while keeping a nice looking design (e.g. with the title left-aligned with y-axis-ticks-labels).

I know it is possible to use other "hacks" (see expected output

It is possible to start with theme(axis.title.y = element_text(angle = 0, vjust = 1)) but the y-axis title is not on top of the line.

what I have so far

This code removes the y-axis title while keeping the theme() parameters defined for the grob:

library(ggplot2)
library(grid)

p <- ggplot(data = iris, aes(x = Sepal.Length, y = Petal.Length))  
  theme(axis.title.y = element_text(angle = 0, vjust = 1),
        axis.title.x = element_blank())
# convert from ggplot to grob object
gp <- ggplotGrob(p)
# locate the grob that corresponds to y-axis title and save its parameters
y.label.grob <- gp$grobs[[which(gp$layout$name == "ylab-l")]]$children
# remove y-axis labels from the plot, & shrink the space occupied by them
gp$grobs[[which(gp$layout$name == "ylab-l")]] <- zeroGrob()
gp$widths[gp$layout$l[which(gp$layout$name == "ylab-l")]] <- unit(0, "cm")

But now I am stuck as I do not know how to use functions from the grid package to move the title where I would like to (i.e. on the top left corner).

CodePudding user response:

You can exceed vjust beyond 1 and adapt the margins a bit. It's hard to get the alignment perfectly though.

library(ggplot2)
library(grid)

ggplot(data = iris, aes(x = Sepal.Length, y = Petal.Length))  
  theme(
    plot.margin = margin(t = 30),
    axis.title.y = element_text(
      angle = 0, vjust = 1.1, 
      margin = margin(r = -50, t = 5.5, b = 5.5, l = 5.5)),
    axis.title.x = element_blank()
  )

If you know the title in advance you can use it's string width.

ggplot(data = iris, aes(x = Sepal.Length, y = Petal.Length))  
  theme(
    plot.margin = margin(t = 30),
    axis.title.y = element_text(
      angle = 0, vjust = 1.07,
      margin = unit.c(
        unit(c(2.75), "pt"),
        unit(-1, "strwidth", data = "Petal.Length"),
        unit(c(2.75, 2.75), "pt")
      )
    ),
    axis.title.x = element_blank()
  )

Created on 2021-09-09 by the enter image description here

  • Related