Левая настройка заголовка в ggplot2 или абсолютная позиция для ggtitle

Я бы хотел, чтобы выровнять заголовок в сюжете, подобном этому

ggplot(data = economics, aes(x = date, y = unemploy)) +
 geom_line() +
 ggtitle("Unemployment in USA between 1967 and 2007") +
 xlab("") +
 ylab("Unemployed [thousands]")

basic ggplot2 plot

Первая попытка

ggplot(data = economics, aes(x = date, y = unemploy)) + geom_line() +
 ggtitle("Unemployment in USA for some years") +
 xlab("") +
 ylab("Unemployed [thousands]") +
 theme(plot.title = element_text(hjust = -0.45, vjust=2.12)))

enter image description here

Успех! Но подождите... там больше... теперь я хочу изменить заголовок на что-то еще.

ggplot(data = economics, aes(x = date, y = unemploy)) +
 geom_line() +
 ggtitle("Unemployment in USA between 1967 and 2007") +
 xlab("") +
 ylab("Unemployed [thousands]") +
 theme(plot.title = element_text(hjust = -0.45, vjust=2.12))

new title

Итак, теперь мне нужно настроить hjust...: (

Вопрос

Как я могу сделать заголовок левым оправданным (пару пикселей слева от ярлыка оси y или так далее) снова и снова, не испортив значение hjust? Или какова связь между hjust и длиной строки?

Я попытался аннотировать вручную в соответствии с этим вопросом, но потом я получил только заголовок и ничего не по какой-то причине - и ошибку.

Спасибо!

Ответ 1

Пока кто-то придумает лучшее решение, один из способов был бы похож на

library(ggplot2)
library(grid)
library(gridExtra)
p <- ggplot(data = economics, aes(x = date, y = unemploy)) +
    geom_line() +
    labs(x = NULL, y = "Unemployed [thousands]", title = NULL)

title.grob <- textGrob(
    label = "Unemployment in USA for some years",
    x = unit(0, "lines"), 
    y = unit(0, "lines"),
    hjust = 0, vjust = 0,
    gp = gpar(fontsize = 16))

p1 <- arrangeGrob(p, top = title.grob)
grid.draw(p1)

enter image description here

Ответ 2

Вы можете вручную настроить макет выхода ggplot. Сначала мы настроили основной сюжет:

library(ggplot2)
p <- ggplot(data = economics, aes(x = date, y = unemploy)) +
 geom_line() +
 labs(title = "Unemployment in USA between 1967 and 2007", 
      x = NULL, y = "Unemployed [thousands]")

Теперь мы можем преобразовать объект ggplot в объект gtable и проверить расположение элементов на графике. Обратите внимание, что title находится в четвертом столбце сетки, в том же столбце, что и главная панель.

g <- ggplotGrob(p)
g$layout
#    t l  b r  z clip       name
# 17 1 1 10 7  0   on background
# 1  5 3  5 3  5  off     spacer
# 2  6 3  6 3  7  off     axis-l
# 3  7 3  7 3  3  off     spacer
# 4  5 4  5 4  6  off     axis-t
# 5  6 4  6 4  1   on      panel
# 6  7 4  7 4  9  off     axis-b
# 7  5 5  5 5  4  off     spacer
# 8  6 5  6 5  8  off     axis-r
# 9  7 5  7 5  2  off     spacer
# 10 4 4  4 4 10  off     xlab-t
# 11 8 4  8 4 11  off     xlab-b
# 12 6 2  6 2 12  off     ylab-l
# 13 6 6  6 6 13  off     ylab-r
# 14 3 4  3 4 14  off   subtitle
# 15 2 4  2 4 15  off      title
# 16 9 4  9 4 16  off    caption

Чтобы выровнять title по левому краю графика, мы можем изменить значение l на 1.

g$layout$l[g$layout$name == "title"] <- 1

Нарисуйте измененную сетку:

grid::grid.draw(g)

Результат: enter image description here

Ответ 3

Другой способ сделать это - использовать theme(). Используйте функцию labs, чтобы пометить все ваши заголовки x = для оси x, y = для оси y, title = для названия сюжета, fill = или colour =, если у вас есть легенда, которую вы хотите поместить в заголовок, Внутри theme() находится hjust = 0, это приведет к тому, что заголовок сюжета останется слева. Вы можете удалить hjust = 0, и название сюжета будет выровнено по центру.

labs(x = 'Sex', y = 'Age Mean', title = 'Suicide 2003-2013 Age Mean by Sex') +
  theme(plot.title = element_text(family = 'Helvetica', 
                              color = '#666666', 
                              face = 'bold', 
                              size = 18, 
                              hjust = 0))

Ответ 4

Я специально написал слой ggdraw() в cowplot, чтобы можно было легко создавать аннотации в любом месте графика. Он устанавливает систему координат, которая охватывает всю область графика, а не только панель графика, и проходит от 0 до 1 как в направлении x, так и в направлении y. Используя этот подход, можно легко разместить заголовок в любом месте.

library(cowplot)
theme_set(theme_gray()) # revert to ggplot2 default theme

p <- ggplot(data = economics, aes(x = date, y = unemploy)) +
  geom_line() +
  ggtitle("") + # make space for title on the plot
  xlab("") +
  ylab("Unemployed [thousands]")

ggdraw(p) + draw_text("Unemployment in USA between 1967 and 2007", 
                      x = 0.01, y = 0.98, hjust = 0, vjust = 1,
                      size = 12)  # default font size is 14, 
                                  # which is too big for theme_gray()

enter image description here

Ответ 5

Этот вопрос относится к этой проблеме с github tidyverse/ggplot2: https://github.com/tidyverse/ggplot2/issues/3252

И это реализовано в ggplot2 (версия для разработчиков): https://github.com/tidyverse/ggplot2/blob/15263f7580d6b5100989f7c1da5d2f5255e480f9/NEWS.md

Темы получили два новых параметра, plot.title.position и plot.caption.position, которые можно использовать для настройки расположения заголовка/субтитра и заголовка графика относительно общего графика (@clauswilke, # 3252).

Чтобы следовать вашему примеру в качестве представителя:

# First install the development version from GitHub:
#install.packages("devtools") #If required
#devtools::install_github("tidyverse/ggplot2")

library(ggplot2)
packageVersion("ggplot2")
#> [1] '3.2.1.9000'

ggplot(data = economics, aes(x = date, y = unemploy)) + 
  geom_line() +
  labs(x=NULL,
       y="Unemployed [thousands]",
       title = "Unemployment in USA for some years",
       subtitle = "A subtitle possibly",
       caption  = "NOTE: Maybe a caption too in italics.") +
  theme(plot.caption = element_text(hjust = 0, face= "italic"), #Default is hjust=1
        plot.title.position = "plot", #NEW parameter. Apply for subtitle too.
        plot.caption.position =  "plot") #NEW parameter

Created on 2019-09-04 by the reprex package (v0.3.0)