0

I have a really long y-axis title with scientific notation that I want to wrap and make center aligned. I can either wrap the title and have it left aligned, or center an incorrect format of the title. How can I wrap the axis title AND have it centered in ggplot2?

Example Data

set.seed(321)
df <- data.frame(matrix(ncol = 2, nrow = 3))
colnames(df)[1:2] <- c("date","value")
df$value <- round(rnorm(3, 100,30),0)
st <- as.Date("2020-01-01")
en <- as.Date("2020-03-31")
df$date <- seq.Date(st,en,by = '1 month')

This makes the ggplot2 figure with the unwrapped long y-axis title

library(ggplot2)

ggplot(df, aes(x = date, y = value)) +
  geom_point() +
  labs(x = "",
       y = expression(paste("Here is a really really really looooonnnng title with notation (  ", m^-2,")"))) +
  scale_x_date(breaks = seq(st, en, by = "1 month"),
               limits = c(st,en),
               date_labels = "%b %Y") +
  scale_y_continuous(limits = c(0,150),
                     breaks=seq(0,150,25)) +
  theme_bw() +
  theme(panel.grid = element_blank(),
        text = element_text(size = 16),
        axis.text.x = element_text(size = 14, color = "black", angle = 90, vjust = 0.5, hjust = 1),
        axis.text.y = element_text(size = 14, color = "black"))

I have tried using \n which wraps the title but, the title is not centered, it is left aligned

ggplot(df, aes(x = date, y = value)) +
  geom_point() +
  labs(x = "",
       y = expression(paste("Here is a really really really \n looooonnnng title with notation (  ", m^-2,")"))) +
  scale_x_date(breaks = seq(st, en, by = "1 month"),
               limits = c(st,en),
               date_labels = "%b %Y") +
  scale_y_continuous(limits = c(0,150),
                     breaks=seq(0,150,25)) +
  theme_bw() +
  theme(panel.grid = element_blank(),
        text = element_text(size = 16),
        axis.text.x = element_text(size = 14, color = "black", angle = 90, vjust = 0.5, hjust = 1),
        axis.text.y = element_text(size = 14, color = "black"))

Using str_wrap() centers the title but the title is no longer formatted correctly

library(stringr)

ggplot(df, aes(x = date, y = value)) +
  geom_point() +
  labs(x = "",
       y = str_wrap(
         expression(paste("Here is a really really really \n looooonnnng title with notation (  ", m^-2,")")),50)
       )+
  scale_x_date(breaks = seq(st, en, by = "1 month"),
               limits = c(st,en),
               date_labels = "%b %Y") +
  scale_y_continuous(limits = c(0,150),
                     breaks=seq(0,150,25)) +
  theme_bw() +
  theme(panel.grid = element_blank(),
        text = element_text(size = 16),
        axis.text.x = element_text(size = 14, color = "black", angle = 90, vjust = 0.5, hjust = 1),
        axis.text.y = element_text(size = 14, color = "black"))

I tried creating a wrapper function based on this similar SO question but it also did not format the title correctly

wrapper <- function(x, ...) 
{
  paste(strwrap(x, ...), collapse = "\n")
}

my_title = expression(paste("Here is a really really really looooonnnng title with notation (  ", m^-2,")"))

ggplot(df, aes(x = date, y = value)) +
  geom_point() +
  labs(x = "",
       y = wrapper(my_title, 50)) +
  scale_x_date(breaks = seq(st, en, by = "1 month"),
               limits = c(st,en),
               date_labels = "%b %Y") +
  scale_y_continuous(limits = c(0,150),
                     breaks=seq(0,150,25)) +
  theme_bw() +
  theme(panel.grid = element_blank(),
        text = element_text(size = 16),
        axis.text.x = element_text(size = 14, color = "black", angle = 90, vjust = 0.5, hjust = 1),
        axis.text.y = element_text(size = 14, color = "black"))
tassones
  • 891
  • 5
  • 18
  • 1
    You should be trying `axis.title.y = element_text( hjust = 0.5)` inside `theme()` (note that it is **title** not **text**) to attempt to center that text, but it still does not work when there is an `expression` in the title. – Gregor Thomas Aug 24 '22 at 15:19
  • @GregorThomas adding `axis.title.y = element_text( hjust = 0.5)` to any of the example figures does not appear to do anything. – tassones Aug 24 '22 at 15:23
  • 1
    @benson23 Your answer seemed to work with some minor edits. If you place `
    ` between where the spacing got dropped and increased the `width` the answer worked. Try `y_lab <- "Here is a really really really looooonnnng
    title with notation (m -2)"` with `width` = 12.
    – tassones Aug 24 '22 at 16:10
  • @tassones If my answer did provide framework for you to build on, I guess I will keep my answer here for future reference. – benson23 Aug 24 '22 at 16:16

1 Answers1

2

You can try to use the package ggtext. If we want to use it, we need to change the normal expression style to HTML and CSS style (which is <sup></sup> for superscript).

For clearer code, I've put your y-axis title into a variable y_lab. The code that is doing the job is theme(axis.title.y = element_textbox_simple(orientation = "left-rotated", halign = 0.5)).

library(ggplot2)
library(ggtext)

y_lab <- "Here is a really really really looooonnnng<br>title with notation (m<sup> -2</sup>)"
ggplot(df, aes(x = date, y = value)) +
  geom_point() +
  labs(x = "",
       y = y_lab)+
  scale_x_date(breaks = seq(st, en, by = "1 month"),
               limits = c(st,en),
               date_labels = "%b %Y") +
  scale_y_continuous(limits = c(0,150),
                     breaks=seq(0,150,25)) +
  theme_bw() +
  theme(panel.grid = element_blank(),
        text = element_text(size = 16),
        axis.text.x = element_text(size = 14, color = "black", angle = 90, vjust = 0.5, hjust = 1),
        axis.text.y = element_text(size = 14, color = "black"),
        axis.title.y = element_textbox_simple(orientation = "left-rotated", halign = 0.5))

tassones
  • 891
  • 5
  • 18
benson23
  • 16,369
  • 9
  • 19
  • 38
  • 1
    @tassones See my update, you can use the `width` argument :) – benson23 Aug 24 '22 at 15:43
  • On my end, when I run the above code, there is no longer a space between the words 'looooonnnng title' for the y-axis title. I have tried adjusting the `width` and it appears no matter which width I use. – tassones Aug 24 '22 at 15:48
  • @tassones Have you tried `ggtext::element_textbox_simple`? – benson23 Aug 24 '22 at 15:53
  • I have tried `y_lab <- "Here is a really really really \n looooonnnng title with notation (m-2)"` with `axis.title.y = ggtext::element_textbox_simple(orientation = "left-rotated", halign = 0.5, width = unit(6, "cm"))` and also `axis.title.y = element_textbox_simple(orientation = "left-rotated", halign = 0.5, width = unit(6, "cm"))` after loading `library(ggtext)`. – tassones Aug 24 '22 at 15:57
  • 1
    @tassones Oh I think I mis-read your question. As I've said in the answer, `ggtext` only supports HTML style elements, so you need to replace `\n` with `
    `
    – benson23 Aug 24 '22 at 16:03