Параллельные участки с 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 248

12 ответов:

любые ggplots бок о бок (или N участков на сетке)

функции grid.arrange() на gridExtra пакет будет объединять несколько участков; это, как вы положили два бок о бок.

require(gridExtra)
plot1 <- qplot(1)
plot2 <- qplot(1)
grid.arrange(plot1, plot2, ncol=2)

это полезно, когда два графика не основаны на одних и тех же данных, например, если вы хотите построить разные переменные без использования reshape().

это будет строить вывод в качестве побочного эффекта. Чтобы распечатать побочный эффект в Файл, укажите устройство драйвер (например pdf,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")

enter image description here

объект 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

patchwork

обновление: этот ответ очень старые. 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)

enter image description here

Дополнительные параметры подробно описаны в эта виньетка.

одна общая жалоба заключается в том, что графики не обязательно выровнены, например, когда они имеют метки оси разного размера, но это по дизайну:grid.arrange не делает никаких попыток специального случая ggplot2 объекты и обрабатывает их одинаково с другими гробами (например, решеточные участки). Он просто помещает гробы в прямоугольную компоновку.

для частного случая объектов ggplot2 я написал другую функцию,ggarrange, с аналогичным интерфейсом, который пытается выровнять панели участков (включая фасетные участки) и пытается соблюдать пропорции, определенные пользователем.

library(egg)
ggarrange(p1, p2, ncol = 2)

обе функции совместимы с ggsave(). Для общего обзора различных вариантов, и какой-то исторический контекст,эта виньетка предлагает дополнительную информацию.

используя tidyverse

x <- rnorm(100)
eps <- rnorm(100,0,.2)
df <- data.frame(x, eps) %>% 
  mutate(p1 = 3*x+eps, p2 = 2*x+eps) %>% 
  tidyr::gather("plot", "value", 3:4) %>% 
  ggplot(aes(x = x , y = value))+ geom_point()+geom_smooth()+facet_wrap(~plot, ncol =2)

df

enter image description here

вышеуказанные решения могут быть неэффективными, если вы хотите построить несколько графиков 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")

enter image description here