Вертикальное выравнивание графиков разной высоты с использованием 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")
Однако этот подход не работает, когда 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")
Я могу навязать свою цель, играя и получая rel_heights
аргумент в порядке, но это не жизнеспособное решение, так как у меня есть много динамических графиков для построения. Здесь оси y выровнены, а координаты всех осей по-прежнему равны.
cowplot::plot_grid(plot1, plot2, ncol = 1, align = "v", rel_heights = c(2, 1.07))
Я видел много подходов к подобным вопросам, которые используют 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))