Выравнивание графиков разной высоты по вертикали с помощью cowplot :: plot_grid () при использовании corre_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(). Возможно, некоторые полезные идеи можно найти в этом родственном подходе.


person Kevin    schedule 22.02.2018    source источник
comment
egg::ggarrange(plot1, plot2) это то, что вам нужно?   -  person user20650    schedule 22.02.2018
comment
Я попробовал egg::ggarrange(plot1, plot2, ncol = 1), и он действительно выполняет вертикальное выравнивание, но координаты оси y не поддерживаются равными координатам оси x. Ось Y немного растягивается на верхнем графике. Кроме того, я больше не могу найти egg на github - меня беспокоит, что он больше не поддерживается.   -  person Kevin    schedule 22.02.2018
comment
жаль, но, возможно, в этом пакете есть другие функции, которые помогают (немного странно, что его нет на github, но это на кране)   -  person user20650    schedule 22.02.2018
comment
Не все программы разрабатываются на github. Сопровождающий egg не разрабатывает на github, но в настоящее время библиотека поддерживается в хорошем состоянии.   -  person Claus Wilke    schedule 23.02.2018
comment
@ClausWilke; немного странно то, что baptiste / egg разрабатывался на github (и есть много ответов на SO, устанавливающий его из github), но с тех пор он был удален из github. huh gridExtra также удален, так что кажется изменение подхода   -  person user20650    schedule 23.02.2018
comment
@ user20650 Да, похоже, gridExtra была доступна на github до версии 2.2.1, а затем была удалена незадолго до выпуска версии 2.3. Может быть, его превратили в частное хранилище.   -  person Claus Wilke    schedule 24.02.2018


Ответы (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)

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

person Claus Wilke    schedule 23.02.2018
comment
Клаус, спасибо за подтверждение того, что egg :: ggarrange () действительно работает. Как вы отметили, раньше меня обманула мысль, что оси все еще не совсем правильные, так это то, что они были расширены по-другому. @ user20650, извините, я пропустил это и усомнился в вашем предложении! ОДНАКО решение egg :: ggarrange () разрушается при включении огранки. Есть предложения, как обобщить это для огранки? Я обновил исходный вопрос, чтобы отразить это. - person Kevin; 23.02.2018
comment
Кевин, пожалуйста, не усложняйте этот вопрос, редактируя его. Лучше принять один из ответов здесь как правильный для исходного вопроса, а затем опубликовать новый вопрос для более сложного случая (с фасетированием). Люди, которые уже ответили, не захотят преследовать движущуюся цель, и люди, которые еще не видели вопрос, вряд ли увидят правку. - person Claus Wilke; 24.02.2018
comment
Хорошо, понял. Новый вопрос здесь: stackoverflow.com/questions/48961927/ - person Kevin; 24.02.2018

По умолчанию диапазон осей на самом деле немного выходит за пределы, указанные в 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))

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

person yang    schedule 23.02.2018