[Перевод] ggplot2: как легко совместить несколько графиков в одном, часть 3

Эта статья шаг за шагом покажет, как совместить несколько ggplot-графиков на одной или нескольких иллюстрациях, с помощью вспомогательных функций, доступных в пакетах R ggpubr, cowplot и gridExtra. Также опишем, как экспортировать полученные графики в файл.

Cмешиваем таблицу, текст и ggplot2-графики


В этом разделе покажем, как вывести таблицу и текст вместе с графиком. Будем использовать набор данных iris.

Начнем с создания таких графиков:

  1. график плотности переменной Sepal.Length. Функция R: ggdensity() [в ggpubr]
  2. сводная таблица, содержащая описательные статистики (среднее, стандартное отклонение, т.д.) Sepal.Length
    • Функция R для вычисления описательных статистик: desc_statby() [в ggpubr]
    • Функция R для создания таблицы с текстом: ggtexttable() [в ggpubr]
  3. абзац текста. Функция R: ggparagraph() [в ggpubr]


Завершим, скомбинировав все три графика с помощью функции ggarrange() [в ggpubr].

# График плотности "Sepal.Length"
#::::::::::::::::::::::::::::::::::::::
density.p <- ggdensity(iris, x = "Sepal.Length", 
                       fill = "Species", palette = "jco")
# Вывести сводную таблицу Sepal.Length
#::::::::::::::::::::::::::::::::::::::
# Вычислить описательные статистики по группам
stable <- desc_statby(iris, measure.var = "Sepal.Length",
                      grps = "Species")
stable <- stable[, c("Species", "length", "mean", "sd")]
# График со сводной таблицей, тема "medium orange" (средний оранжевый)
stable.p <- ggtexttable(stable, rows = NULL, 
                        theme = ttheme("mOrange"))
# Вывести текст
#::::::::::::::::::::::::::::::::::::::
text <- paste("iris data set gives the measurements in cm",
              "of the variables sepal length and width",
              "and petal length and width, respectively,",
              "for 50 flowers from each of 3 species of iris.",
             "The species are Iris setosa, versicolor, and virginica.", sep = " ")
text.p <- ggparagraph(text = text, face = "italic", size = 11, color = "black")
# Разместить графики на странице
ggarrange(density.p, stable.p, text.p, 
          ncol = 1, nrow = 3,
          heights = c(1, 0.5, 0.3))


59d0f8d99f5bd954291631.png

Добавляем графический элемент в ggplot


Для добавления таблиц, графиков или других элементов на основе таблиц в рабочую область ggplot есть функция annotation_custom() [в ggplot2]. Упрощенный формат:

annotation_custom(grob, xmin, xmax, ymin, ymax)


  • grob: внешний графический элемент для отображения
  • xmin, xmax: x-расположение в координатах (горизонтальное расположение)
  • ymin, ymax: y-расположение в координатах (вертикальное расположение)


Помещаем таблицу в ggplot


Используем графики density.p и stable.p, созданные в предыдущем разделе.

density.p + annotation_custom(ggplotGrob(stable.p),
                              xmin = 5.5, ymin = 0.7,
                              xmax = 8)


59d0fa516bce7002084486.png

Помещаем диаграмму рассеивания в ggplot


  1. Создаем диаграмму разброса для y = «Sepal.Width» по x = «Sepal.Length» из набора данных iris. Функция R: ggscatter() [ggpubr].
  2. Создаем отдельно диаграмму рассеивания переменных х и у с прозрачным фоном. Функция R: ggboxplot() [ggpubr].
  3. Преобразуем диаграмму рассеивания в графический объект под названием «grob» в терминологии Grid. Функция R: ggplotGrob() [ggplot2].
  4. Поместим grob-ы диаграммы рассеивания внутрь диаграммы разброса. Функция R: annotation_custom() [ggplot2].


Поскольку помещенная внутрь диаграмма рассеивания накладывается в нескольких точках, для нее используется прозрачный фон.

# Диаграмма разброса по группам ("Species")
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
sp <- ggscatter(iris, x = "Sepal.Length", y = "Sepal.Width",
                color = "Species", palette = "jco",
                size = 3, alpha = 0.6)
# Диаграммы рассеивания переменных x/y
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# Диаграмма рассеивания переменной x
xbp <- ggboxplot(iris$Sepal.Length, width = 0.3, fill = "lightgray") +
  rotate() +
  theme_transparent()
# Диаграмма рассеивания переменной у
ybp <- ggboxplot(iris$Sepal.Width, width = 0.3, fill = "lightgray") +
  theme_transparent()
# Создать внешние графические объекты
# под названием "grob” в терминологии Grid
xbp_grob <- ggplotGrob(xbp)
ybp_grob <- ggplotGrob(ybp)
# Поместить диаграммы рассеивания в диаграмму разброса
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
xmin <- min(iris$Sepal.Length); xmax <- max(iris$Sepal.Length)
ymin <- min(iris$Sepal.Width); ymax <- max(iris$Sepal.Width)
yoffset <- (1/15)*ymax; xoffset <- (1/15)*xmax
# Вставить xbp_grob внутрь диаграммы разброса
sp + annotation_custom(grob = xbp_grob, xmin = xmin, xmax = xmax, 
                       ymin = ymin-yoffset, ymax = ymin+yoffset) +
  # Вставить ybp_grob внутрь диаграммы разброса
  annotation_custom(grob = ybp_grob,
                       xmin = xmin-xoffset, xmax = xmin+xoffset, 
                       ymin = ymin, ymax = ymax)


59d0ff305bbb9254062271.png

Добавляем фоновое изображение в ggplot2-графики


Импортировать фоновое изображение. Используйте или функцию readJPEG() [в пакете jpeg], или функцию readPNG() [в пакете png] в зависимости от формата фоновой картинки.

Чтобы протестировать пример ниже, убедитесь, что пакет png установлен. Можно его установить, используя команду install.packages("png”).

# Импорт картинки
img.file <- system.file(file.path("images", "background-image.png"),
                        package = "ggpubr")
img <- png::readPNG(img.file)


Скомбинировать ggplot с фоновой картинкой. Функция R: background_image() [в ggpubr].

library(ggplot2)
library(ggpubr)
ggplot(iris, aes(Species, Sepal.Length))+
  background_image(img)+
  geom_boxplot(aes(fill = Species), color = "white")+
  fill_palette("jco")


59d119729c402936444527.png
Изменим прозрачность заливки в диаграммах разброса заданием аргумента alpha. Значение должно быть в промежутке [0, 1], где 0 — полная прозрачность, а 1 — отсутствие прозрачности.

library(ggplot2)
library(ggpubr)
ggplot(iris, aes(Species, Sepal.Length))+
  background_image(img)+
  geom_boxplot(aes(fill = Species), color = "white", alpha = 0.5)+
  fill_palette("jco")


59d11a28b196f810686056.png
Еще один пример, накладывание карты Франции на ggplot2:

mypngfile <- download.file("https://upload.wikimedia.org/wikipedia/commons/thumb/e/e4/France_Flag_Map.svg/612px-France_Flag_Map.svg.png", 
                           destfile = "france.png", mode = 'wb') 
img <- png::readPNG('france.png') 
ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width)) +
  background_image(img)+
  geom_point(aes(color = Species), alpha = 0.6, size = 5)+
  color_palette("jco")+
  theme(legend.position = "top")


59d11a821d341405106490.png

Располагаем графики на нескольких страницах


Если у вас длинный список ggplot-ов, скажем, n=20, возможно, вы захотите упорядочить их, разместив на нескольких страницах. Если на странице будет 4 графика, для 20 понадобится 5 страниц.

Функция ggarrange() [в ggpubr] предоставляет удобное решение, чтобы расположить несколько ggplot-ов на нескольких страницах. После задания аргументов nrow и ncol функция ggarrange() автоматически рассчитывает количество страниц, которое потребуется, чтобы разместить все графики. Она возвращает список упорядоченных ggplot-ов.

Например, код ниже

multi.page <- ggarrange(bxp, dp, bp, sp,
                        nrow = 1, ncol = 2)


возвращает две страницы с двумя графиками на каждой. Можно вывести каждую страницу вот так:

multi.page[[1]] # Вывести страницу 1
multi.page[[2]] # Вывести страницу 2


Упорядоченные графики можно экспортировать в pdf-файл с помощью функции ggexport() [в ggpubr]:

ggexport(multi.page, filename = "multi.page.ggplot2.pdf")


PDF-файл

Многостраничный вывод можно получить и с функцией marrangeGrob() [в gridExtra].

library(gridExtra)
res <- marrangeGrob(list(bxp, dp, bp, sp), nrow = 1, ncol = 2)
# Экспорт в pdf-файл
ggexport(res, filename = "multi.page.ggplot2.pdf")
# Интерактивный вывод
res


Вложенное взаиморасположение с ggarrange ()


Упорядочим графики, созданные в предыдущих разделах.

p1 <- ggarrange(sp, bp + font("x.text", size = 9),
                ncol = 1, nrow = 2)
p2 <- ggarrange(density.p, stable.p, text.p, 
                ncol = 1, nrow = 3,
                heights = c(1, 0.5, 0.3))
ggarrange(p1, p2, ncol = 2, nrow = 1)


59d11d49ed582984919556.png

Экспорт графиков


Функция R: ggexport() [в ggpubr].

Сначала создадим список из 4 ggplot-ов, соответствующих переменным Sepal.Length, Sepal.Width, Petal.Length и Petal.Width в наборе данных iris.

plots <- ggboxplot(iris, x = "Species",
                   y = c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width"),
                   color = "Species", palette = "jco"
                   )
plots[[1]]  # Вывести первый график
plots[[2]]  # Вывести второй график и т.д.


После можно экспортировать отдельные графики в файл (pdf, eps или png) (один график на странице). Можно упорядочить графики (2 на страницу) при экспорте.

Экспорт отдельных графиков в pdf (по одному на странице):

ggexport(plotlist = plots, filename = "test.pdf")


Упорядочьте и экспортируйте. Задайте nrow и ncol, чтобы вывести несколько графиков на одной странице:

ggexport(plotlist = plots, filename = "test.pdf",
         nrow = 2, ncol = 1)

© Habrahabr.ru