Parcela lado a lado con ggplot2

Me gustaría ubicar dos gráficos uno al lado del otro usando el paquete ggplot2 , es decir, hacer el equivalente de par(mfrow=c(1,2)) .

Por ejemplo, me gustaría que los siguientes dos gráficos se muestren uno al lado del otro con la misma escala.

 x <- rnorm(100) eps <- rnorm(100,0,.2) qplot(x,3*x+eps) qplot(x,2*x+eps) 

¿Debo ponerlos en el mismo data.frame?

 qplot(displ, hwy, data=mpg, facets = . ~ year) + geom_smooth() 

Cualquier ggplots uno al lado del otro (o n plots en una cuadrícula)

La función grid.arrange() en el paquete gridExtra combinará múltiples gráficos; así es como pones dos al lado del otro.

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

Esto es útil cuando las dos gráficas no están basadas en los mismos datos, por ejemplo, si desea graficar diferentes variables sin usar reshape ().

Esto trazará la salida como un efecto secundario. Para imprimir el efecto secundario a un archivo, especifique un controlador de dispositivo (como pdf , png , etc.), por ejemplo

 pdf("foo.pdf") grid.arrange(plot1, plot2) dev.off() 

o use arrangeGrob() en combinación con ggsave() ,

 ggsave("foo.pdf", arrangeGrob(plot1, plot2)) 

Esto es el equivalente de hacer dos plots distintas usando par(mfrow = c(1,2)) . Esto no solo ahorra tiempo organizando datos, sino que es necesario cuando desea dos gráficos diferentes.


Apéndice: Usar facetas

Las facetas son útiles para hacer gráficas similares para diferentes grupos. Esto se señala a continuación en muchas respuestas a continuación, pero quiero resaltar este enfoque con ejemplos equivalentes a los gráficos anteriores.

 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) 

Actualizar

la función plot_grid en cowplot vale la pena cowplot como una alternativa a grid.arrange . Vea la respuesta de @ claus-wilke a continuación y esta viñeta para un enfoque equivalente; pero la función permite controles más finos en la ubicación y el tamaño de la gráfica, según esta viñeta .

Una desventaja de las soluciones basadas en grid.arrange es que dificultan la etiqueta de las gráficas con letras (A, B, etc.), como lo requieren la mayoría de las revistas.

Escribí el paquete cowplot para resolver este (y algunos otros) problemas, específicamente la función 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

El objeto que plot_grid() es otro objeto ggplot2, y puede guardarlo con ggsave() como de costumbre:

 p <- plot_grid(iris1, iris2, labels = "AUTO") ggsave("plot.pdf", p) 

Alternativamente, puede usar la función save_plot() , que es un envoltorio delgado alrededor de ggsave() que facilita la obtención de las dimensiones correctas para los gráficos combinados, por ejemplo:

 p <- plot_grid(iris1, iris2, labels = "AUTO") save_plot("plot.pdf", p, ncol = 2) 

(El argumento ncol = 2 le dice a save_plot() que hay dos gráficos uno al lado del otro, y save_plot() hace que la imagen guardada sea dos veces más ancha).

Para una descripción más detallada de cómo organizar plots en una cuadrícula, vea esta viñeta. También hay una viñeta que explica cómo hacer ttwigs con una leyenda compartida.

Un punto frecuente de confusión es que el paquete cowplot cambia el tema predeterminado ggplot2. El paquete se comporta de esa manera porque fue escrito originalmente para usos internos de laboratorio, y nunca usamos el tema predeterminado. Si esto causa problemas, puede usar uno de los siguientes tres enfoques para evitarlos:

1. Configure el tema manualmente para cada plot. Creo que es una buena práctica especificar siempre un tema en particular para cada gráfico, tal como lo hice con + theme_bw() en el ejemplo anterior. Si especifica un tema en particular, el tema predeterminado no importa.

2. Invierta el tema predeterminado a la configuración predeterminada de ggplot2. Puedes hacer esto con una línea de código:

 theme_set(theme_gray()) 

3. Llame a las funciones de cowplot sin conectar el paquete. Tampoco puede llamar a la library(cowplot) o require(cowplot) y en su lugar llamar a las funciones cowplot cowplot:: . Por ejemplo, el ejemplo anterior que utiliza el tema predeterminado ggplot2 se convertiría en:

 ## Commented out, we don't call this # library(cowplot) iris1 <- ggplot(iris, aes(x = Species, y = Sepal.Length)) + geom_boxplot() iris2 <- ggplot(iris, aes(x = Sepal.Length, fill = Species)) + geom_density(alpha = 0.7) + theme(legend.position = c(0.8, 0.8)) cowplot::plot_grid(iris1, iris2, labels = "AUTO") 

enter image description here

Actualización: a partir de ggplot2 3.0.0, los gráficos se pueden etiquetar directamente, ver, por ejemplo, aquí.

Puede usar la siguiente función multiplot del libro de cocina R de Winston Chang

 multiplot(plot1, plot2, cols=2) 

 multiplot <- function(..., plotlist=NULL, cols) { require(grid) # Make a list from the ... arguments and plotlist plots <- c(list(...), plotlist) numPlots = length(plots) # Make the panel plotCols = cols # Number of columns of plots plotRows = ceiling(numPlots/plotCols) # Number of rows needed, calculated from # of cols # Set up the page grid.newpage() pushViewport(viewport(layout = grid.layout(plotRows, plotCols))) vplayout <- function(x, y) viewport(layout.pos.row = x, layout.pos.col = y) # Make each plot, in the correct location for (i in 1:numPlots) { curRow = ceiling(i/plotCols) curCol = (i-1) %% plotCols + 1 print(plots[[i]], vp = vplayout(curRow, curCol )) } } 

Sí, creo que necesitas organizar tus datos de manera apropiada. Una forma sería esta:

 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() 

Estoy seguro de que hay mejores trucos en Plyr o remodelación. Todavía no estoy realmente al tanto de todos estos potentes paquetes de Hadley.

Usando el paquete de remodelación puedes hacer algo como esto.

 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) 

Usando el paquete de mosaico , simplemente puede usar + operador:

 # 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 

labor de retazos

Actualización: esta respuesta es muy antigua. gridExtra::grid.arrange() es ahora el enfoque recomendado. Dejo esto aquí en caso de que pueda ser útil.


Stephen Turner publicó la función arrange() en el blog Getting Genetics Done (ver la publicación para las instrucciones de la aplicación)

 vp.layout <- function(x, y) viewport(layout.pos.row=x, layout.pos.col=y) arrange <- function(..., nrow=NULL, ncol=NULL, as.table=FALSE) { dots <- list(...) n <- length(dots) if(is.null(nrow) & is.null(ncol)) { nrow = floor(n/2) ; ncol = ceiling(n/nrow)} if(is.null(nrow)) { nrow = ceiling(n/ncol)} if(is.null(ncol)) { ncol = ceiling(n/nrow)} ## NOTE see n2mfrow in grDevices for possible alternative grid.newpage() pushViewport(viewport(layout=grid.layout(nrow,ncol) ) ) ii.p <- 1 for(ii.row in seq(1, nrow)){ ii.table.row <- ii.row if(as.table) {ii.table.row <- nrow - ii.table.row + 1} for(ii.col in seq(1, ncol)){ ii.table <- ii.p if(ii.p > n) break print(dots[[ii.table]], vp=vp.layout(ii.table.row, ii.col)) ii.p <- ii.p + 1 } } } 

ggplot2 se basa en gráficos de cuadrícula, que proporcionan un sistema diferente para organizar diagtwigs en una página. El comando par(mfrow...) no tiene un equivalente directo, ya que los objetos de grilla (llamados grobs ) no necesariamente se dibujan inmediatamente, sino que se pueden almacenar y manipular como objetos R normales antes de convertirse a una salida gráfica. Esto permite una mayor flexibilidad que el diseño de este modelo de gráficos base, pero la estrategia es necesariamente un poco diferente.

Escribí grid.arrange() para proporcionar una interfaz simple lo más cercana posible a par(mfrow) . En su forma más simple, el código se vería así:

 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

Más opciones están detalladas en esta viñeta .

Una queja común es que las gráficas no están necesariamente alineadas, por ejemplo, cuando tienen tags de ejes de diferentes tamaños, pero esto es por diseño: grid.arrange no intenta objetos de ggplot2 de casos especiales, y los trata por igual a otros grobs (plots de celosía) , por ejemplo). Simplemente coloca grobs en un diseño rectangular.

Para el caso especial de los objetos ggplot2, escribí otra función, ggarrange , con una interfaz similar, que intenta alinear los paneles de trazado (incluidos los trazados facetados) e intenta respetar las relaciones de aspecto cuando lo define el usuario.

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

Ambas funciones son compatibles con ggsave() . Para obtener una descripción general de las diferentes opciones y algún contexto histórico, esta viñeta ofrece información adicional .

Usando 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

Las soluciones anteriores pueden no ser eficientes si quiere trazar múltiples ggplot usando un bucle (por ejemplo, como se pregunta aquí: Crear múltiples gráficas en ggplot con diferentes valores del eje Y usando un bucle ), que es un paso deseado para analizar lo desconocido ( o grandes) conjuntos de datos (por ejemplo, cuando quiere trazar los recuentos de todas las variables en un conjunto de datos).

El siguiente código muestra cómo hacerlo usando el ‘multiplot ()’ mencionado anteriormente, cuyo origen está aquí: 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) } 

Ahora ejecuta la función - para obtener los recuentos de todas las variables impresas usando ggplot en una página

 dt = ggplot2::diamonds plotAllCounts(dt) 

Una cosa a tener en cuenta es que:
usando aes(get(strX)) , que normalmente ggplot en bucles cuando trabajas con ggplot , en el código anterior en lugar de aes_string(strX) NO dibujará los gráficos deseados. En cambio, trazará la última ttwig muchas veces. No he averiguado por qué: puede que tenga que hacer que los aes y aes_string se ggplot en ggplot .

De lo contrario, espero que encuentres la función útil.

También hay un paquete multipanelfigure que vale la pena mencionar. Ver también esta respuesta .

 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 

Creado en 2018-07-06 por el paquete reprex (v0.2.0.9000).

El paquete cowplot le ofrece una buena manera de hacerlo, de una manera que se adapte a la publicación.

 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