plots plot_grid manipulation ggplot change r ggplot2 cowplot

plot_grid - ¿Cómo alinear un ggplot ordinario con uno facetado en el cowplot?



plot grid r (4)

Estoy tratando de organizar las parcelas de una manera lista para publicación con el uso del paquete cowplot .
Solo quiero que los paneles sean del mismo tamaño y etiquetados.

Ejemplo reproducible

library(ggplot2) library(cowplot) gg1 <- ggplot(mtcars)+ geom_point(aes(x=mpg,y=hp))+ theme_bw()+ theme(aspect.ratio=1) gg2 <- ggplot(mtcars)+ geom_point(aes(x=mpg,y=hp,fill=cyl))+ facet_wrap(~cyl,ncol=2)+ theme_bw()+ theme(aspect.ratio=1, legend.position=''none'') output <- plot_grid(gg1,gg2, labels = c(''A'',''B''),label_size = 20) print(output)

El código produce esta trama.

Como puede ver, ni los ejes horizontales coinciden, ni los bordes superiores de los paneles.

El argumento align desde cowplot no funciona con gráficos facetados.

¿Algunas ideas?


Actualización: el paquete de egg está en CRAN ahora
https://cran.r-project.org/web/packages/egg/index.html

Solo quiero agregar que @ baptiste ha creado un gran paquete experimental de huevos, que cumple con lo que escribió en su respuesta :

Instálelo desde github ( https://github.com/baptiste/egg )

library("devtools") install_github("baptiste/egg")

Entonces simplemente haz

library("egg") ggarrange(gg1, gg2, ncol=2)

Puedes agregar etiquetas manualmente:

ap <- ggarrange(gg1,gg2, ncol=2) ggdraw(ap) + draw_plot_label(label=c("a","b"), x=c(0,0.5), y=c(1,1))

(Cuando intenté agregar primero las etiquetas a las parcelas individuales, las parcelas no se organizaron correctamente).


Aquí hay una solución basada en esta idea.

library(ggplot2) library(grid) library(gridExtra) library(gtable) gtable_frame <- function(g, width=unit(1,"null"), height=unit(1,"null")){ panels <- g[["layout"]][grepl("panel", g[["layout"]][["name"]]), ] ll <- unique(panels$l) tt <- unique(panels$t) fixed_ar <- g$respect if(fixed_ar) { # there lies madness, want to align despite aspect ratio constraints ar <- as.numeric(g$heights[tt[1]]) / as.numeric(g$widths[ll[1]]) height <- width * ar g$respect <- FALSE } core <- g[seq(min(tt), max(tt)), seq(min(ll), max(ll))] top <- g[seq(1, min(tt)-1), ] bottom <- g[seq(max(tt)+1, nrow(g)), ] left <- g[, seq(1, min(ll)-1)] right <- g[, seq(max(ll)+1, ncol(g))] fg <- nullGrob() lg <- if(length(left)) g[seq(min(tt), max(tt)), seq(1, min(ll)-1)] else fg rg <- if(length(right)) g[seq(min(tt), max(tt)), seq(max(ll)+1,ncol(g))] else fg grobs = list(fg, g[seq(1, min(tt)-1), seq(min(ll), max(ll))], fg, lg, g[seq(min(tt), max(tt)), seq(min(ll), max(ll))], rg, fg, g[seq(max(tt)+1, nrow(g)), seq(min(ll), max(ll))], fg) widths <- unit.c(sum(left$widths), width, sum(right$widths)) heights <- unit.c(sum(top$heights), height, sum(bottom$heights)) all <- gtable_matrix("all", grobs = matrix(grobs, ncol=3, nrow=3, byrow = TRUE), widths = widths, heights = heights) all[["layout"]][5,"name"] <- "panel" # make sure knows where the panel is for nested calls if(fixed_ar) all$respect <- TRUE all } p1 <- ggplot(mtcars)+ geom_point(aes(x=mpg,y=hp))+ theme_bw()+ theme(aspect.ratio=1) p2 <- ggplot(mtcars)+ geom_point(aes(x=mpg,y=hp,fill=cyl))+ facet_wrap(~cyl,ncol=2)+ theme_bw()+ theme(aspect.ratio=1, legend.position=''none'') g1 <- ggplotGrob(p1) g2 <- ggplotGrob(p2) fg1 <- gtable_frame(g1) fg2 <- gtable_frame(g2) grid.newpage() grid.draw(cbind(fg1, fg2))

Tenga en cuenta que la función gtable_frame envuelve trazados en función de sus paneles, pero excluyendo las tiras de paneles por diseño (me parece más agradable).


He aquí un truco hasta que alguien encuentre una respuesta más elegante: puede usar grid.arrange del paquete gridExtra para cambiar los tamaños relativos de los dos gráficos para que los ejes se gridExtra . El parámetro w en el código a continuación es lo que controla eso al darle a la gráfica de la izquierda un poco más del ancho horizontal, lo que la hace relativamente más grande, en comparación con la gráfica de la derecha.

library(gridExtra) w = 0.512 grid.arrange(gg1, gg2, widths=c(w,1-w), ncol=2)

También puede usar arrangeGrob y textGrob para agregar los títulos "A" y "B" a cada gráfico.

w = 0.512 grid.arrange(arrangeGrob(textGrob("A", x=0.13, gp=gpar(fontface="bold", cex=1.4)), gg1, heights=c(0.03,0.97)), arrangeGrob(textGrob("B", x=0.13, gp=gpar(fontface="bold", cex=1.4)), gg2, heights=c(0.03,0.97)), widths=c(w,1-w), ncol=2)

En cualquier caso, necesita ajustar w a mano para alinear los gráficos (que es lo que hace que este método, por así decirlo, sea subóptimo). El valor apropiado para w cambiará dependiendo del tamaño físico de la parcela. w=0.512 pareció funcionar bien cuando guardé la gráfica a continuación como un png de 1000 x 500 píxeles.

Una mejor respuesta probablemente implique algo análogo a esta respuesta SO , pero adaptada para alinear diagramas facetados y no facetados (o, más generalmente, diagramas que no tienen una correspondencia de uno a uno entre sus grobs constituyentes).


Ya que esta es una de las preguntas más votadas con respecto a la gráfica de vacas y las alineaciones complejas, quise señalar que la parcela ahora tiene algunas funciones para alinear parcelas facetadas. (Soy el autor del paquete). Sin embargo, ¡no funcionan en este caso particular!

Por ejemplo, esto funciona (usando la opción de axis en plot_grid() ):

gg1 <- ggplot(mtcars) + geom_point(aes(x=mpg, y=hp)) + theme_bw() gg2 <- ggplot(mtcars)+ geom_point(aes(x=mpg, y=hp, fill=cyl)) + facet_wrap(~cyl, ncol=2) + theme_bw() + theme(legend.position=''none'') plot_grid(gg1, gg2, labels = c(''A'',''B''), label_size = 20, align = ''h'', axis = ''tb'')

También podemos hacer esto de la siguiente manera, para obtener un tipo diferente de alineación (dependiendo de si desea que la tira de faceta se cuente o no como parte de la trama):

plot_grid(gg1, gg2, labels = c(''A'', ''B''), label_size = 20, align = ''h'', axis = ''b'')

Ahora, ¿por qué dije que no funciona para este caso? Porque, si miras el código original en la pregunta, verás que había un theme(aspect.ratio=1) que theme(aspect.ratio=1) . cowplot puede alinear gráficos siempre que no fuerce una relación de aspecto específica, porque el método que utiliza para alinear gráficos generalmente modifica la relación de aspecto de los gráficos individuales.