- PVSM.RU - https://www.pvsm.ru -

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

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

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))

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

Добавляем графический элемент в 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)

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

Помещаем диаграмму рассеивания в 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)

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

Добавляем фоновое изображение в 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")

ggplot2: как легко совместить несколько графиков в одном, часть 3 - 4
Изменим прозрачность заливки в диаграммах разброса заданием аргумента 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")

ggplot2: как легко совместить несколько графиков в одном, часть 3 - 5
Еще один пример, накладывание карты Франции на 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")

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

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

Если у вас длинный список 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-файл [4]

Многостраничный вывод можно получить и с функцией 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)

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

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

Функция 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)

Автор: Анна Каплун

Источник [5]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/vizualizatsiya/264733

Ссылки в тексте:

[1] ggpubr: http://www.sthda.com/english/rpkgs/ggpubr/index.html

[2] cowplot: https://cran.r-project.org/web/packages/cowplot/vignettes/introduction.html

[3] gridExtra: https://github.com/danielinteractive/gridextra

[4] PDF-файл: https://www.slideshare.net/kassambara/multipageggplot2

[5] Источник: https://habrahabr.ru/post/339090/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best