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