Добавление нескольких аннотаций при фасетировании - PullRequest
2 голосов
/ 28 мая 2020

У меня возникли проблемы с добавлением нескольких аннотаций (с использованием векторов) к графику с фасетами.

Например:

library(tidyverse) # ggplot2_3.3.0

tibble(t = 1:100) %>% 
  crossing(id = LETTERS[1:2]) %>% 
  group_by(id) %>% 
  mutate(y = cumsum(rnorm(n()))) %>% 
  ggplot(aes(t, y)) + # perhaps add `group = id` if you don't facet by `id`
  facet_wrap(vars(id)) + # (1)
  annotate('rect', xmin = 20, xmax = 30, ymin = -Inf, ymax = Inf, fill = 'grey60') + # (2)
  annotate('rect', xmin = 30, xmax = 40, ymin = -Inf, ymax = Inf, fill = 'grey70') + # (2)
  annotate('rect', xmin = 40, xmax = 50, ymin = -Inf, ymax = Inf, fill = 'grey80') + # (2)
  annotate('rect', xmin = 50, xmax = 60, ymin = -Inf, ymax = Inf, fill = 'grey90') + # (2)
  # annotate('rect', ymin = -Inf, ymax = Inf,                # (3)
  #          xmin = seq(20, by=10, len=4),                   # (3)
  #          xmax = seq(30, by=10, len=4),                   # (3)
  #          fill = paste0('grey', seq(60, by=10, len=4))) + # (3)
  geom_line() +
  theme_light()

Приведенный выше код создает желаемый график (в частности, мне нужна одинаковая аннотация на всех фасетах). Однако команда annotate повторяется четыре раза; кроме того, на странице справки для annotate говорится, что «свойства геометрии ... передаются как векторы». Так что естественно попробовать закомментировать строки (2) и раскомментировать строки (3). К сожалению, это приводит к ошибке

Error: Aesthetics must be either length 1 or the same as the data (8): fill

Обратите внимание: если вы дополнительно закомментируете строку (1) (и при желании добавите group = id к эстетике), то это не приведет к ошибке.

1 Ответ

2 голосов
/ 28 мая 2020

Для обсуждения этого поведения ggplot2 см. gihub . Поскольку проблема была закрыта и, насколько я понимаю, вы ничего не можете сделать, используя annotate. Однако для достижения желаемого вы можете просто использовать geom_rect, например:

library(tidyverse) # ggplot2_3.3.0

df_annotate <- data.frame(
  xmin = seq(20, 50, 10),
  xmax = seq(30, 60, 10),
  ymin = -Inf,
  ymax = Inf,
  fill = paste0("grey", seq(60, 90, 10))
)

tibble(t = 1:100) %>% 
  crossing(id = LETTERS[1:4]) %>% 
  group_by(id) %>% 
  mutate(y = cumsum(rnorm(n()))) %>% 
  ggplot() + 
  geom_rect(aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax, fill = fill), data = df_annotate) +
  geom_line(aes(t, y)) +
  scale_fill_identity() +
  facet_wrap(vars(id)) +
  theme_light()

Создано 28 мая 2020 года Пакет репекс (v0.3.0)

Редактировать Используя ggnewscale, можно иметь вторую или ... шкалу заполнения:

library(tidyverse) # ggplot2_3.3.0
library(ggnewscale)

df_annotate <- data.frame(
  xmin = seq(20, 50, 10),
  xmax = seq(30, 60, 10),
  ymin = -Inf,
  ymax = Inf,
  fill = paste0("grey", seq(60, 90, 10))
)

df <- tibble(t = 1:100) %>% 
  crossing(id = LETTERS[1:4]) %>% 
  group_by(id) %>% 
  mutate(y = cumsum(rnorm(n())))

ggplot() + 
  geom_rect(aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax, fill = fill), data = df_annotate) +
  scale_fill_identity() +
  new_scale_fill() +
  geom_area(data = df, aes(t, y, fill = id)) +
  facet_wrap(vars(id)) +
  theme_light()

Создано 29.05.2020 с помощью пакета . (v0.3.0)

...