Después de de una prolongada selección de información hemos podido solucionar esta aprieto que pueden tener ciertos de nuestros lectores. Te brindamos la respuesta y nuestro deseo es resultarte de mucha apoyo.
Solución:
Puede ajustar el ancho de un objeto ggplot usando gráficos de cuadrícula
g = ggplot(df, aes(x,y,color=i)) +
geom_point() +
facet_grid(labely~labelx, scales='free_x', space='free_x')
library(grid)
gt = ggplot_gtable(ggplot_build(g))
gt$widths[4] = 4*gt$widths[4]
grid.draw(gt)
Con gráficos complejos con muchos elementos, puede resultar un poco engorroso determinar qué ancho desea modificar. En este caso, era la columna 4 de la cuadrícula la que necesitaba expandirse, pero esto variará para diferentes parcelas. Hay varias formas de determinar cuál cambiar, pero una forma bastante sencilla y buena es utilizar gtable_show_layout
desde el gtable
paquete.
gtable_show_layout(gt)
produce la siguiente imagen:
en el que podemos ver que la faceta de la izquierda está en la columna número 4. Las primeras 3 columnas dan espacio para el margen, el título del eje y las etiquetas del eje + ticks. La columna 5 es el espacio entre las facetas, la columna 6 es la faceta de la derecha. Las columnas 7 a 12 son para las etiquetas de la faceta derecha, los espacios, la leyenda y el margen derecho.
Una alternativa a inspeccionar una representación gráfica de gtable es simplemente inspeccionar la propia tabla. De hecho, si necesita automatizar el proceso, esta sería la forma de hacerlo. Así que echemos un vistazo a TableGrob:
gt
# TableGrob (13 x 12) "layout": 25 grobs
# z cells name grob
# 1 0 ( 1-13, 1-12) background rect[plot.background..rect.399]
# 2 1 ( 7- 7, 4- 4) panel-1-1 gTree[panel-1.gTree.283]
# 3 1 ( 9- 9, 4- 4) panel-2-1 gTree[panel-3.gTree.305]
# 4 1 ( 7- 7, 6- 6) panel-1-2 gTree[panel-2.gTree.294]
# 5 1 ( 9- 9, 6- 6) panel-2-2 gTree[panel-4.gTree.316]
# 6 3 ( 5- 5, 4- 4) axis-t-1 zeroGrob[NULL]
# 7 3 ( 5- 5, 6- 6) axis-t-2 zeroGrob[NULL]
# 8 3 (10-10, 4- 4) axis-b-1 absoluteGrob[GRID.absoluteGrob.329]
# 9 3 (10-10, 6- 6) axis-b-2 absoluteGrob[GRID.absoluteGrob.336]
# 10 3 ( 7- 7, 3- 3) axis-l-1 absoluteGrob[GRID.absoluteGrob.343]
# 11 3 ( 9- 9, 3- 3) axis-l-2 absoluteGrob[GRID.absoluteGrob.350]
# 12 3 ( 7- 7, 8- 8) axis-r-1 zeroGrob[NULL]
# 13 3 ( 9- 9, 8- 8) axis-r-2 zeroGrob[NULL]
# 14 2 ( 6- 6, 4- 4) strip-t-1 gtable[strip]
# 15 2 ( 6- 6, 6- 6) strip-t-2 gtable[strip]
# 16 2 ( 7- 7, 7- 7) strip-r-1 gtable[strip]
# 17 2 ( 9- 9, 7- 7) strip-r-2 gtable[strip]
# 18 4 ( 4- 4, 4- 6) xlab-t zeroGrob[NULL]
# 19 5 (11-11, 4- 6) xlab-b titleGrob[axis.title.x..titleGrob.319]
# 20 6 ( 7- 9, 2- 2) ylab-l titleGrob[axis.title.y..titleGrob.322]
# 21 7 ( 7- 9, 9- 9) ylab-r zeroGrob[NULL]
# 22 8 ( 7- 9,11-11) guide-box gtable[guide-box]
# 23 9 ( 3- 3, 4- 6) subtitle zeroGrob[plot.subtitle..zeroGrob.396]
# 24 10 ( 2- 2, 4- 6) title zeroGrob[plot.title..zeroGrob.395]
# 25 11 (12-12, 4- 6) caption zeroGrob[plot.caption..zeroGrob.397]
Los bits relevantes son
# cells name
# ( 7- 7, 4- 4) panel-1-1
# ( 9- 9, 4- 4) panel-2-1
# ( 6- 6, 4- 4) strip-t-1
en el que los nombres panel-xy se refieren a paneles en coordenadas x, y, y las celdas dan las coordenadas (como rangos) de ese panel nombrado en la tabla. Entonces, por ejemplo, los paneles superior e inferior izquierdo están ubicados en las celdas de la tabla con los rangos de columna 4- 4
. (solo en la columna cuatro, eso es). La franja superior izquierda también está en la columna de celda 4.
Si desea utilizar esta tabla para encontrar el ancho relevante mediante programación, en lugar de manualmente, (utilizando la faceta superior izquierda, es decir "panel-1-1"
como ejemplo) podrías usar
gt$layout$l[grep('panel-1-1', gt$layout$name)]
# [1] 4
Ah si muy triste esa funcionalidad para configurar widths
y heights
en facet_grid
se ha ido.
Otra posible solución sin ggplotGrob
es establecer el ángulo del texto en theme(strip.text.x=element_text(angle...))
y el ajuste de texto de facetas facet_grid(... labeller=label_wrap_gen(width...))
, p.ej
ggplot(df, aes(x,y,color=i)) +
geom_point() +
facet_grid(labely~labelx, scales='free_x', space='free_x', labeller=label_wrap_gen(width = 10, multi_line = TRUE)) +
theme(strip.text.x=element_text(angle=90, hjust=0.5, vjust=0.5))
En caso de que esté interesado en modificar ggplot2
en más y otras formas, Recomiendo la viñeta:
vignette("extending-ggplot2")
Ahora, para su problema en cuestión, creo que el atajo de una solución limpia es el siguiente:
library(ggplot2)
DF <- data.frame(labelx = rep(c('my long label','short'), c(2,26)),
labely = rep(c('a','b'), each = 14),
x = c(letters[1:2], letters[1:26]),
y = LETTERS[6:7],
i = rnorm(28))
# ad-hoc replacement for the "draw_panels" method, sorry for the hundred lines of code...
# only modification is marked with a comment
draw_panels_new <- function(panels, layout, x_scales, y_scales, ranges, coord, data, theme, params) % theme$panel.spacing)
panel_table <- gtable_add_row_space(panel_table, theme$panel.spacing.y %
Continuando en un nuevo bloque de código para detener el desplazamiento:
# need to pre-set the same environment to find things like e.g.
# gtable_matrix() from package gtable
environment(draw_panels_new) <- environment(FacetGrid$draw_panels)
# assign custom method
FacetGrid$draw_panels <- draw_panels_new
# happy plotting
ggplot(DF, aes(x, y, color = i)) +
geom_point() +
facet_grid(labely~labelx, scales = 'free_x', space = 'free_x')
Digo atajo porque, por supuesto, podrías escribir tu propia versión de facet_grid_new
además, te permite pasar los valores c(1,4)
desde arriba de forma flexible como extra params
.
Y, por supuesto, podrías hacer el tuyo ggproto
objeto heredado de FacetGrid
...
Editar:
Otra forma sencilla de hacer esto más flexible sería agregar un option
, por ejemplo, como:
options(facet_size_manual = list(width = c(1,4), height = NULL))
Esto podría usarse dentro de la costumbre. draw_panels
método de alguna manera como este:
if (!is.null(facet_width <- getOption("facet_size_manual")$width))
widths <- facet_width
No se te olvide dar visibilidad a este enunciado si si solucionó tu problema.