Reputation: 2977
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 this using subtitle), but here I look for a solution using the grid approach. I am also aware that it is possible to move around the title by setting margins
but it requires to uptade it all the time and I was not able to get a satisfying result with it.
Then, using grid
functions as demonstrated in this SO post seems the way to go.
Here is what I would like to get:
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.
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).
Upvotes: 2
Views: 1339
Reputation: 38053
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 reprex package (v2.0.1)
Upvotes: 2
Reputation: 4708
You could use cowplot
as another approach:
library(ggplot2)
library(cowplot)
title <- ggdraw() +
draw_label(
"Petal.Length",
#fontface = 'bold',
x = 0,
hjust = 0
) +
theme(
# add margin on the left of the drawing canvas,
# so title is aligned with left edge of first plot
plot.margin = margin(0, 0, 0, 7)
)
p <- ggplot(data = iris, aes(x = Sepal.Length, y = Petal.Length)) +
labs(y = "")
plot_row <- plot_grid(p)
plot_grid(
title, plot_row,
ncol = 1,
rel_heights = c(0.1, 1)
)
Upvotes: 0