Вертикальное выравнивание графиков разной высоты с использованием cowplot::plot_grid() при использовании ordin_equal()

Я пытаюсь объединить два объекта ggplot, используя cowplot::plot_grid() и вертикально выровнять их. Обычно это довольно просто, используя align = "v",

dat1 <- data.frame(x = rep(1:10, 2), y = 1:20)
dat2 <- data.frame(x = 1:10, y = 1:10)
plot1 <- ggplot(dat1, aes(x = x, y = y)) + geom_point()
plot2 <- ggplot(dat2, aes(x = x, y = y)) + geom_point()
cowplot::plot_grid(plot1, plot2, ncol = 1, align = "v")

изображение 1

Однако этот подход не работает, когда ggplots используют coord_equal() так как plot_grid() не может изменить оси, когда соотношение сторон принудительно. Вместо этого по умолчанию значения высоты каждого графика остаются неизменными.

plot1 <- ggplot(dat1, aes(x = x, y = y)) + geom_point() + coord_equal()
plot2 <- ggplot(dat2, aes(x = x, y = y)) + geom_point() + coord_equal()
cowplot::plot_grid(plot1, plot2, ncol = 1, align = "v")

изображение 2

Я могу навязать свою цель, играя и получая rel_heights аргумент в порядке, но это не жизнеспособное решение, так как у меня есть много динамических графиков для построения. Здесь оси y выровнены, а координаты всех осей по-прежнему равны.

cowplot::plot_grid(plot1, plot2, ncol = 1, align = "v", rel_heights = c(2, 1.07))

изображение 3

Я видел много подходов к подобным вопросам, которые используют ggplot2::ggplotGrob() а также grid::grid_draw(), но ничто не доходит до этих вопросов, когда coord_equal() используется. Возможно, лучшее решение не использует cowplot::plot_grid() или, возможно, решение каким-то образом динамически определяет и передает правильные значения rel_heights, Я думаю, что я предпочел бы более поздний вариант, чтобы иметь возможность легко использовать другие функции, которые идут с cowplot::plot_grid(), Возможно, в этом связанном подходе можно найти полезное вдохновение.

2 ответа

Решение

Автор cowplot::plot_grid() Вот. Это не работает, когда вы пытаетесь выровнять графики с указанным соотношением сторон, которое вы генерируете при использовании coord_equal(), Решение состоит в том, чтобы использовать либо библиотеку яиц, либо библиотеку пэчворка. Пэчворк все еще находится в разработке, но скоро должен быть выпущен в CRAN. В то же время, вы можете установить с GitHub.

Вот решение с использованием яйца. Мне кажется, что это работает просто отлично.

library(ggplot2)
library(egg)

dat1 <- data.frame(x = rep(1:10, 2), y = 1:20)
dat2 <- data.frame(x = 1:10, y = 1:10)
plot1 <- ggplot(dat1, aes(x = x, y = y)) + geom_point() + coord_equal()
plot2 <- ggplot(dat2, aes(x = x, y = y)) + geom_point() + coord_equal()
ggarrange(plot1, plot2, ncol = 1)

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

Две незначительные проблемы, которые я вижу, заключаются в том, что (1) тики осей для двух осей y различны, и это создает впечатление, что расстояние отличается, и (2) оси расширяются до разных пределов. Вы можете обойти как ручную установку тиков, так и расширение.

plot1 <- ggplot(dat1, aes(x = x, y = y)) + geom_point() + 
  scale_y_continuous(limits = c(0, 21), breaks = 5*(0:4), expand = c(0, 0)) +
  coord_equal()
plot2 <- ggplot(dat2, aes(x = x, y = y)) + geom_point() + 
  scale_y_continuous(limits = c(0, 11), breaks = 5*(0:4), expand = c(0, 0)) +
  coord_equal()
ggarrange(plot1, plot2, ncol = 1)

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

По умолчанию диапазон осей фактически расширяется за пределы ggplot. expand аргумент в функции scale_continuous/discrete() был использован для установки удлинителей. Как в scale_continuous() документация:

Числовой вектор длины два, дающий мультипликативные и аддитивные константы расширения. Эти константы обеспечивают размещение данных на некотором расстоянии от осей. Значения по умолчанию: c(0.05, 0) для непрерывных переменных и c(0, 0.6) для дискретных переменных.

library(ggplot2)
dat1 <- data.frame(x = rep(1:10, 2), y = 1:20)
dat2 <- data.frame(x = 1:10, y = 1:10)
plot1 <- ggplot(dat1, aes(x = x, y = y)) + geom_point() + coord_equal()
plot2 <- ggplot(dat2, aes(x = x, y = y)) + geom_point() + coord_equal()

Во-первых, мы можем рассчитать фактическую высоту этих двух участков, этот пост объясняет, как expand аргумент работы.

# The defaults are c(0.05, 0) for your continuous variables
limity1 <- max(dat1$y) - min(dat1$y)
y1 <- limity1 + 2 * limity1 * 0.05
limity2 <- max(dat2$y) - min(dat2$y)
y2 <- limity2 + 2 * limity2 * 0.05

Затем используйте пэчворк, чтобы составить эти два сюжета.

library(patchwork)
#  actual heights of plots was used to set the heights argment
plot1 + plot2 + plot_layout(ncol = 1, heights = c(y1, y2))

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

Другие вопросы по тегам