facet_wrap: пометить (цветной рамкой, линией и заголовком) один конкретный график

Можно ли пометить конкретный сюжет facet_wrap с помощью ggplot2?

Предположим, у меня есть график 3x3 facet_wrap, и я хочу отметить средний (i=2,j=2), придав ему красную рамку, красный цвет линии и красный цвет заголовка. Как это сделать красиво и удобно?


person Squeezie    schedule 04.06.2018    source источник
comment
Боюсь, простого решения нет. Самый простой способ - создать N отдельных участков и объединить их с пакетами egg, ggpubr или cowplot.   -  person pogibas    schedule 04.06.2018


Ответы (1)


Как упоминалось в комментариях, сделать то, что вы предлагаете, непросто. Вот как можно это сделать. Здесь я создаю образец фрейма данных и загружаю пакеты ggplot2 и grid.

library(ggplot2)
library(grid)

set.seed(123)
df <- data.frame(f = rep(LETTERS[1:9], 3), x = rnorm(27), y = rnorm(27))

Теперь я создаю основной сюжет. Красная линия — самая простая: мы сопоставляем эстетику colour с переменной, которую используем для огранки, и устанавливаем цвет в scale_colour_manual:

p <- ggplot(df, aes(x, y, colour = f == "E")) +
  geom_line() +
  scale_colour_manual(guide = FALSE, values = c("black", "red")) +
  facet_wrap("f")

В остальном приходится редактировать график вручную. Мы генерируем график и проверяем его:

g <- ggplotGrob(p)
g
# TableGrob (21 x 15) "layout": 62 grobs
#     z         cells        name                                           grob
# 1   0 ( 1-21, 1-15)  background               rect[plot.background..rect.5921]
# 2   1 ( 7- 7, 4- 4)   panel-1-1                      gTree[panel-1.gTree.5502]
# ...
# 6   1 (12-12, 8- 8)   panel-2-2                      gTree[panel-5.gTree.5562]
# ...
# 51  2 (11-11, 8- 8) strip-t-2-2                                  gtable[strip]
# ...
# 62 10 (20-20, 4-12)     caption          zeroGrob[plot.caption..zeroGrob.5919]

Интересующие гробы — это номера 6 и 51, соответствующие центральной панели и ее полосе панели соответственно. Осматривая гроб номер 6, мы видим следующее:

str(g$grobs[[6]])
# List of 5
#  $ name         : chr "panel-5.gTree.5562"
#  ...
#  $ children     :List of 5
#   ..$ grill.gTree.5560           :List of 5
#   .. ..$ name         : chr "grill.gTree.5560"
# ...
#   .. ..$ children     :List of 5
#   .. .. ..$ panel.background..rect.5551      :List of 10
# ...
#   .. .. .. ..$ gp    :List of 4
#   .. .. .. .. ..$ lwd : num 1.42
#   .. .. .. .. ..$ col : logi NA
#   .. .. .. .. ..$ fill: chr "grey92"
#   .. .. .. .. ..$ lty : num 1
#   .. .. .. .. ..- attr(*, "class")= chr "gpar"
# ...
#  - attr(*, "class")= chr [1:3] "gTree" "grob" "gDesc"

Обратите внимание на элемент col. Присваиваем этому элементу значение red:

g$grobs[[6]]$children[[1]]$children[[1]]$gp$col <- "red"

Проверяем grob 51 (у него немного другая структура), делаем то же самое:

g$grobs[[51]]$grobs[[1]]$children[[2]]$children[[1]]$gp$col <- "red"

Это все, что нам нужно сделать. Хотя для проверки структур grob требуется некоторое усилие, для внесения изменений требуется не так много кода. Подводя итог, вот все, что нам нужно сделать:

g <- ggplotGrob(p)
g$grobs[[6]]$children[[1]]$children[[1]]$gp$col <- "red"
g$grobs[[51]]$grobs[[1]]$children[[2]]$children[[1]]$gp$col <- "red"
grid.draw(g)

получить:

введите здесь описание изображения

person Weihuang Wong    schedule 04.06.2018
comment
Это хорошо написанное решение и прекрасно выполненное. Он работает точно так же, как в вашем образце. Молодец и спасибо! - person Squeezie; 04.06.2018
comment
Знаете ли вы, как изменить цвет левой границы фона полосы?. Это изменяет все границы, но не только одну: g$grobs[[51]]$grobs[[1]]$children[[1]]$gp$col - person Alvaro Morales; 11.05.2021