¿Cómo puedo obtener una cuadrícula "no balanceada" de ggplots?

94

Con grid.arrangepuedo organizar varias ggplotfiguras en una cuadrícula para lograr una figura de varios paneles usando algo como:

library(ggplot2)
library(grid)
library(gridExtra)

generar algunos gráficos ggplot2, luego

plot5 <- grid.arrange(plot4, plot1, heights=c(3/4, 1/4), ncol=1, nrow=2)

¿Cómo puedo obtener un diseño de 2 columnas 'desequilibrado' con una parcela en toda la primera columna y tres parcelas en la segunda columna? Jugué con un enfoque de 'cuadrícula de cuadrículas' tratando de usar grid.arrangepara trazar una cuadrícula (por ejemplo plot5, arriba) contra otra trama, pero obtuve:

Error en arreglarGrob (..., as.table = as.table, clip = clip, main = main,: ¡la entrada debe ser grobs!

Actualizar:

Gracias por el consejo. Examinaré viewportsy grid. Mientras tanto, gracias a @DWin, la layOutfunción en el paquete 'wq' funcionó muy bien para la figura de compilación en mi Sweavedocumento: ingrese la descripción de la imagen aquí

Actualización 2:

El arrangeGrobcomando (como lo sugiere @baptiste) también funciona bien y parece muy intuitivo; al menos fue fácil alterar el ancho de las dos columnas. También tiene la ventaja de no requerir el paquete 'wq'.

Por ejemplo, aquí está el código de mi archivo Sweave:

<<label=fig5plot, echo=F, results=hide>>=
plot5<-grid.arrange(plot4, arrangeGrob(plot1, plot2, plot3, ncol=1), 
                    ncol=2, widths=c(1,1.2))
@
\begin{figure}[]
    \begin{center}
<<label=fig5,fig=TRUE,echo=T, width=10,height=12>>=
<<fig5plot>>
@
\end{center}
\caption{Combined plots using the `arrangeGrob' command.}
\label{fig:five}
\end{figure}

que produce la siguiente salida: ingrese la descripción de la imagen aquí

Por cierto, ¿alguien me dice por qué aparece '> NA'?

usuario441706
fuente
Es posible que tenga que configurar las ventanas gráficas usted mismo, grid.arrangepuede que no sea lo suficientemente flexible (busque stackoverflow para "[r] ventana
gráfica de
2
@BenBolker le ha indicado una dirección fructífera utilizando grid. Consulte también el libro ggplot2 de Hadley, Sección 8.4.2.
Ari B. Friedman
1
@BenBolker grid.arrangese puede usar con viewports anidados usando su compañero arrangeGrob(esencialmente devolviendo a gTree), como en el ejemplo que di a continuación.
baptiste
1
su asignación final a plot5no es necesaria ya que grid.arrangeno devuelve nada (NULL). Si desea guardar el grob resultante, úselo arrangeGrobnuevamente (y grid.drawpara mostrarlo).
baptiste

Respuestas:

73

grid.arrangedibuja directamente en el dispositivo; si desea combinarlo con otros objetos de cuadrícula que necesita arrangeGrob, como en

 p = rectGrob()
 grid.arrange(p, arrangeGrob(p,p,p, heights=c(3/4, 1/4, 1/4), ncol=1),
              ncol=2)

Editar (07/2015): con v> 2.0.0 puede usar el layout_matrixargumento,

 grid.arrange(p,p,p,p, layout_matrix = cbind(c(1,1,1), c(2,3,4)))
baptiste
fuente
6
¿Podría explicar cómo la cbind(c(1,1,1), c(2,3,4))matriz describe la disposición de las figuras?
Ron Gejman
5
@RonGejman es fácil si imprime la matriz 3x2 en la pantalla: la primera columna son todos 1, ahí es donde vive la primera trama, que abarca las tres filas; la segunda columna contiene las parcelas 2, 3, 4, cada una ocupando una fila.
baptiste
17

Intenté resolverlo con la cuadrícula y pensé que lo tenía abajo, pero terminé fallando (aunque mirando ahora el código en la función que cito a continuación, puedo ver que estaba muy cerca ... :-)

El paquete 'wq' tiene una layOutfunción que lo hará por usted:

p1 <- qplot(mpg, wt, data=mtcars)
layOut(list(p1, 1:3, 1),   # takes three rows and the first column
        list(p1, 1, 2),    # next three are on separate rows
         list(p1, 2,2), 
          list(p1, 3,2))

ingrese la descripción de la imagen aquí

IRTFM
fuente
¡Vaya, esa es una función útil! Sin embargo, creo que copiar + pegar puede haberle fallado; quiso decir para g1, g2, etc para todos ser p1?
joran
3
@joran: Lo hice. No recuerdo cuál de las "tres virtudes de la programación" es la pereza, pero sé que está ahí en alguna parte.
IRTFM
¡Gracias! Funcionó muy bien. Véase más arriba.
user441706
2

Otra alternativa es el patchworkpaquete de Thomas Lin Pedersen.

# install.packages("devtools")
# devtools::install_github("thomasp85/patchwork")
library(patchwork)

Genere algunas parcelas.

p1 <- ggplot(mtcars) + geom_point(aes(mpg, disp)) + facet_grid(rows = vars(gear))
p2 <- ggplot(mtcars) + geom_boxplot(aes(gear, disp, group = gear))
p3 <- ggplot(mtcars) + geom_smooth(aes(disp, qsec))
p4 <- ggplot(mtcars) + geom_bar(aes(carb))

Ahora arregle las parcelas.

p1 + (p2 / p3 / p4)

ingrese la descripción de la imagen aquí

Markus
fuente
1

También hay un paquete multipanelfigure que vale la pena mencionar. Vea 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 = 3, panel_label_type = "upper-roman")

figure1 %<>%
  fill_panel(q1, column = 1, row = 1:3) %<>%
  fill_panel(q2, column = 2, row = 1) %<>%
  fill_panel(q3, column = 2, row = 2) %<>%
  fill_panel(q4, column = 2, row = 3)
#> `geom_smooth()` using method = 'loess' and formula 'y ~ x'
figure1

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

Tung
fuente