Параллельные участки с ggplot2
Я хотел бы разместить два участка бок о бок с помощью пакета ggplot2, т. е. не эквивалентно par(mfrow=c(1,2))
.
например, я хотел бы, чтобы следующие два графика были показаны бок о бок с одинаковым масштабом.
x <- rnorm(100)
eps <- rnorm(100,0,.2)
qplot(x,3*x+eps)
qplot(x,2*x+eps)
мне нужно поместить их в те же данные.кадр?
qplot(displ, hwy, data=mpg, facets = . ~ year) + geom_smooth()
12 ответов:
любые ggplots бок о бок (или N участков на сетке)
функции
grid.arrange()
наgridExtra
пакет будет объединять несколько участков; это, как вы положили два бок о бок.require(gridExtra) plot1 <- qplot(1) plot2 <- qplot(1) grid.arrange(plot1, plot2, ncol=2)
это полезно, когда два графика не основаны на одних и тех же данных, например, если вы хотите построить разные переменные без использования reshape().
это будет строить вывод в качестве побочного эффекта. Чтобы распечатать побочный эффект в Файл, укажите устройство драйвер (например
png
и т. д.), Например,pdf("foo.pdf") grid.arrange(plot1, plot2) dev.off()
или
arrangeGrob()
в сочетании сggsave()
,ggsave("foo.pdf", arrangeGrob(plot1, plot2))
это эквивалентно созданию двух различных участков с использованием
par(mfrow = c(1,2))
. Это не только экономит время упорядочивания данных, это необходимо, когда вы хотите два разных графика.
Приложение: Использование Фасетов
фасеты полезны для создания одинаковых графиков для разных групп. Это указано ниже во многих ответах ниже, но я хочу подчеркнуть этот подход с примерами, эквивалентными приведенным выше сюжетам.
mydata <- data.frame(myGroup = c('a', 'b'), myX = c(1,1)) qplot(data = mydata, x = myX, facets = ~myGroup) ggplot(data = mydata) + geom_bar(aes(myX)) + facet_wrap(~myGroup)
обновление
the на
cowplot
стоит проверить в качестве альтернативыgrid.arrange
. Смотрите ответ по @claus-wilke ниже и эта виньетка для эквивалентного подхода; но функция позволяет более точно контролировать местоположение и размер участка, основываясь на эта виньетка.
один недостаток решений, основанных на
grid.arrange
это то, что они затрудняют маркировку участков буквами (A, B и т. д.), как требует большинство журналов.я написал cowplot пакет для решения этой (и нескольких других) проблем, в частности функции
plot_grid()
:library(cowplot) iris1 <- ggplot(iris, aes(x = Species, y = Sepal.Length)) + geom_boxplot() + theme_bw() iris2 <- ggplot(iris, aes(x = Sepal.Length, fill = Species)) + geom_density(alpha = 0.7) + theme_bw() + theme(legend.position = c(0.8, 0.8)) plot_grid(iris1, iris2, labels = "AUTO")
объект
plot_grid()
returns-это еще один объект ggplot2, и вы можете сохранить его с помощьюggsave()
как обычно:p <- plot_grid(iris1, iris2, labels = "AUTO") ggsave("plot.pdf", p)
кроме того, вы можете использовать функцию cowplot
save_plot()
, который представляет собой тонкую оболочку вокругggsave()
это позволяет легко получить правильные размеры для комбинированных участков, например:p <- plot_grid(iris1, iris2, labels = "AUTO") save_plot("plot.pdf", p, ncol = 2)
(The
Да, я думаю, что вам нужно правильно организовать свои данные. Один из способов будет таким:
X <- data.frame(x=rep(x,2), y=c(3*x+eps, 2*x+eps), case=rep(c("first","second"), each=100)) qplot(x, y, data=X, facets = . ~ case) + geom_smooth()
Я уверен, что есть лучшие трюки в plyr или reshape - я все еще не очень в курсе на всех этих мощных пакетах Хэдли.
С помощью пакета reshape вы можете сделать что-то вроде этого.
library(ggplot2) wide <- data.frame(x = rnorm(100), eps = rnorm(100, 0, .2)) wide$first <- with(wide, 3 * x + eps) wide$second <- with(wide, 2 * x + eps) long <- melt(wide, id.vars = c("x", "eps")) ggplot(long, aes(x = x, y = value)) + geom_smooth() + geom_point() + facet_grid(.~ variable)
С помощью пэчворк пакета, вы можете просто использовать
+
оператор:# install.packages("devtools") devtools::install_github("thomasp85/patchwork") library(ggplot2) p1 <- ggplot(mtcars) + geom_point(aes(mpg, disp)) p2 <- ggplot(mtcars) + geom_boxplot(aes(gear, disp, group = gear)) library(patchwork) p1 + p2
обновление: этот ответ очень старые.
gridExtra::grid.arrange()
теперь рекомендуемый подход. Я оставлю это здесь на случай, если это может быть полезным.
Стивен Тернер опубликовано на
ggplot2 основан на сетке графики, которые обеспечивают другую систему для размещения участков на странице. Элемент
par(mfrow...)
команда не имеет прямого эквивалента, как объекты сетки (называется grobs) не обязательно рисуются сразу, но могут храниться и управляться как обычные объекты R перед преобразованием в графический вывод. Это обеспечивает большую гибкость, чем нарисуйте это сейчас модель базовой графики, но стратегии обязательно немного отличающийся.я писал
grid.arrange()
чтобы обеспечить простой интерфейс как можно ближе кpar(mfrow)
. В самом простом виде код будет выглядеть так:library(ggplot2) x <- rnorm(100) eps <- rnorm(100,0,.2) p1 <- qplot(x,3*x+eps) p2 <- qplot(x,2*x+eps) library(gridExtra) grid.arrange(p1, p2, ncol = 2)
Дополнительные параметры подробно описаны в эта виньетка.
одна общая жалоба заключается в том, что графики не обязательно выровнены, например, когда они имеют метки оси разного размера, но это по дизайну:
grid.arrange
не делает никаких попыток специального случая ggplot2 объекты и обрабатывает их одинаково с другими гробами (например, решеточные участки). Он просто помещает гробы в прямоугольную компоновку.для частного случая объектов ggplot2 я написал другую функцию,
ggarrange
, с аналогичным интерфейсом, который пытается выровнять панели участков (включая фасетные участки) и пытается соблюдать пропорции, определенные пользователем.library(egg) ggarrange(p1, p2, ncol = 2)
обе функции совместимы с
ggsave()
. Для общего обзора различных вариантов, и какой-то исторический контекст,эта виньетка предлагает дополнительную информацию.
вышеуказанные решения могут быть неэффективными, если вы хотите построить несколько графиков ggplot с использованием цикла (например, как указано здесь:создание нескольких участков в ggplot с различными значениями оси Y с помощью цикла), что является желательным шагом в анализе неизвестных (или больших) наборов данных (например, когда вы хотите построить количество всех переменных в наборе данных).
приведенный ниже код показывает, как это сделать с помощью упомянутого выше ' multiplot ()', источник которого находится здесь: http://www.cookbook-r.com/Graphs/Multiple_graphs_on_one_page_(ggplot2):
plotAllCounts <- function (dt){ plots <- list(); for(i in 1:ncol(dt)) { strX = names(dt)[i] print(sprintf("%i: strX = %s", i, strX)) plots[[i]] <- ggplot(dt) + xlab(strX) + geom_point(aes_string(strX),stat="count") } columnsToPlot <- floor(sqrt(ncol(dt))) multiplot(plotlist = plots, cols = columnsToPlot) }
теперь запустите функцию-чтобы получить подсчеты для всех переменных, напечатанных с помощью ggplot на одной странице
dt = ggplot2::diamonds plotAllCounts(dt)
одна вещь, чтобы отметить, что:
используяaes(get(strX))
, который вы обычно используете в циклах при работе сggplot
, В приведенном выше коде вместоaes_string(strX)
не будет рисовать нужные участки. Вместо этого он будет строить последний сюжет много раз. Я еще не разобрался почему - это, возможно, придется сделатьaes
иaes_string
называютggplot
.в противном случае, надеюсь, что вы найдете эту функцию полезной.
есть еще пакет multipanelfigure это стоит упомянуть. Смотрите также это ответ.
library(ggplot2) theme_set(theme_bw()) q1 <- ggplot(mtcars) + geom_point(aes(mpg, disp)) q2 <- ggplot(mtcars) + geom_boxplot(aes(gear, disp, group = gear)) q3 <- ggplot(mtcars) + geom_smooth(aes(disp, qsec)) q4 <- ggplot(mtcars) + geom_bar(aes(carb)) library(magrittr) library(multipanelfigure) figure1 <- multi_panel_figure(columns = 2, rows = 2, panel_label_type = "none") # show the layout figure1
figure1 %<>% fill_panel(q1, column = 1, row = 1) %<>% fill_panel(q2, column = 2, row = 1) %<>% fill_panel(q3, column = 1, row = 2) %<>% fill_panel(q4, column = 2, row = 2) figure1
# complex layout figure2 <- multi_panel_figure(columns = 3, rows = 3, panel_label_type = "upper-roman") figure2
figure2 %<>% fill_panel(q1, column = 1:2, row = 1) %<>% fill_panel(q2, column = 3, row = 1) %<>% fill_panel(q3, column = 1, row = 2) %<>% fill_panel(q4, column = 2:3, row = 2:3) figure2
создано на 2018-07-06 по reprex package (версии v0.2.0.9000).
The
cowplot
пакет дает вам хороший способ сделать это, таким образом, который соответствует публикации.x <- rnorm(100) eps <- rnorm(100,0,.2) A = qplot(x,3*x+eps, geom = c("point", "smooth"))+theme_gray() B = qplot(x,2*x+eps, geom = c("point", "smooth"))+theme_gray() cowplot::plot_grid(A, B, labels = c("A", "B"), align = "v")