Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to center ggplot plot title

The "lege artis" way to center justify a plot title in ggplot - plot.title = element_text(hjust = 0.5) - centers the title over plot area excluding axis labels.

This can get ugly when the axis labels are very long, such as this plot of songs in Mary Poppins Soundtrack vs. their character length.

length of songs in Mary Poppins Soundrack

library(tidyverse)

mary_poppins <- data_frame(song = c("Overture", "Sister Suffragette", "The Life I Lead", "The Perfect Nanny", "A Spoonful of Sugar", "Pavement Artist", "Jolly Holiday", "Supercalifragilisticexpialidocious", "Stay Awake", "I Love to Laugh", "A British Bank", "Feed the Birds ", "Fidelity Fiduciary Bank", "Chim Chim Cher-ee", "Step in Time", "A Man Has Dreams", "Let's Go Fly a Kite"
))

mary_poppins <- mary_poppins %>%
  mutate(len = nchar(song))

ggplot(data = mary_poppins, aes(x = reorder(song, len), y = len)) +
  geom_col(fill = "firebrick") +
  coord_flip() +
  theme_light() +
  theme(axis.title.y = element_blank(),
        axis.text = element_text(size = rel(1.5)),
        plot.title = element_text(size = rel(2.5), face = "bold", hjust = 0.5, 
                                  margin = margin(t = 10, b = 20, unit = "pt"))) +
  ggtitle("Mary Poppins") +
  ylab("Lenght of title (characters)")

Is there a way to center the title over the total plot area, i.e . including the area taken over by axis labels?

like image 477
Jindra Lacko Avatar asked Sep 18 '17 19:09

Jindra Lacko


3 Answers

A simple way to solve the problem is to add the following to the plot:

theme(plot.title.position = 'plot', 
      plot.title = element_text(hjust = 0.5))

The first part tells ggplot to use the entire plot as a reference for the centering, and the second part centers the title.

like image 35
Umberto Mignozzetti Avatar answered Sep 28 '22 09:09

Umberto Mignozzetti


As I replied in an essentially duplicate question, you can use the patchwork library and it's plot_annotation, so you'll have:

library(tidyverse)

mary_poppins <- data_frame(song = c("Overture", "Sister Suffragette", "The Life I Lead", "The Perfect Nanny", "A Spoonful of Sugar", "Pavement Artist", "Jolly Holiday", "Supercalifragilisticexpialidocious", "Stay Awake", "I Love to Laugh", "A British Bank", "Feed the Birds ", "Fidelity Fiduciary Bank", "Chim Chim Cher-ee", "Step in Time", "A Man Has Dreams", "Let's Go Fly a Kite"
))
mary_poppins <- mary_poppins %>%
  mutate(len = nchar(song))

ggplot(data = mary_poppins, aes(x = reorder(song, len), y = len)) +
  geom_col(fill = "firebrick") +
  coord_flip() +
  theme_light() +
  theme(axis.title.y = element_blank(),
        axis.text = element_text(size = rel(1.5))) +
  patchwork::plot_annotation("Mary Poppins", 
        theme = theme(plot.title = element_text(size = rel(2.5), face = "bold", hjust = 0.5, 
                                  margin = margin(t = 10, b = 20, unit = "pt")))) +
  ylab("Lenght of title (characters)")

Since plot_annotation is designed for multipanel plots, it will not inherit the theme of the plot you are constructing, so you need to give it separately. It will however honor any global theme.

The resulting plot is (hopefully) what you need.

plot with centered title

like image 45
Martin Modrák Avatar answered Sep 28 '22 10:09

Martin Modrák


Short solution I've found:

theme(plot.title = element_text(hjust = -0.2))

hjust parameter controls distance from the left alignment to the y axis. Negative values move text to the left

like image 105
Angel Lopez Sanz Avatar answered Sep 28 '22 10:09

Angel Lopez Sanz