r - Justificación de múltiples leyendas en ggmap/ggplot2
r-grid (1)
Estoy tratando de hacer un mapa con dos leyendas que denoten forma y color ("Tipo" y "Org" en el siguiente ejemplo), y tengo las inserciones insertadas. Puedo colocar las leyendas, pero me gustaría que quedaran justificadas para que sus bordes izquierdos se alineen. No puedo hacer nada más que centrado uno con respecto al otro:
require(ggplot2)
require(ggmap)
require(grid)
require(mapproj)
data <- data.frame(Org=rep(c("ABCDEFG","HIJKLMNOP","QRSTUVWX"),4)
, Type=rep(c("Y","Z"),6), Lat=runif(12,48,54.5)
, Long=runif(12,-133.5,-122.5))
osmMap <- get_map(location=c(-134,47.5,-122,55), source = ''osm'')
points <- geom_jitter(data=data, aes(Long, Lat, shape=Type
, colour=Org))
legend <- theme(legend.justification=c(0,0), legend.position=c(0,0)
, legend.margin=unit(0,"lines"), legend.box="vertical"
, legend.key.size=unit(1,"lines"), legend.text.align=0
, legend.title.align=0)
ggmap(osmMap) + points + legend
Esta opción ahora está disponible en ggplot2 0.9.3.1, use
ggmap(osmMap) + points + legend + theme(legend.box.just = "left")
Solución antigua, manual:
Aquí hay una solución:
require(gtable)
require(ggplot2)
require(ggmap)
require(grid)
require(mapproj)
# Original data
data <- data.frame(Org=rep(c("ABCDEFG","HIJKLMNOP","QRSTUVWX"),4),
Type=rep(c("Y","Z"),6), Lat=runif(12,48,54.5),
Long=runif(12,-133.5,-122.5))
osmMap <- get_map(location=c(-134,47.5,-122,55), source = ''google'')
points <- geom_jitter(data=data, aes(Long, Lat, shape=Type, colour=Org))
legend <- theme(legend.justification=c(0,0), legend.position=c(0,0),
legend.margin=unit(0,"lines"), legend.box="vertical",
legend.key.size=unit(1,"lines"), legend.text.align=0,
legend.title.align=0)
# Data transformation
p <- ggmap(osmMap) + points + legend
data <- ggplot_build(p)
gtable <- ggplot_gtable(data)
# Determining index of legends table
lbox <- which(sapply(gtable$grobs, paste) == "gtable[guide-box]")
# Each legend has several parts, wdth contains total widths for each legend
wdth <- with(gtable$grobs[[lbox]], c(sum(as.vector(grobs[[1]]$widths)),
sum(as.vector(grobs[[2]]$widths))))
# Determining narrower legend
id <- which.min(wdth)
# Adding a new empty column of abs(diff(wdth)) mm width on the right of
# the smaller legend box
gtable$grobs[[lbox]]$grobs[[id]] <- gtable_add_cols(
gtable$grobs[[lbox]]$grobs[[id]],
unit(abs(diff(wdth)), "mm"))
# Plotting
grid.draw(gtable)
Esto no depende de Type
u Org
. Sin embargo, esto no sería suficiente con más de dos leyendas. Además, en caso de que haga algunos cambios para alterar la lista de grobs (objetos gráficos), es posible que necesite cambiar grobs[[8]]
a grobs[[i]]
donde i
es la posición de sus leyendas, consulte gtable$grobs
y busque TableGrob (5 x 3) "guide-box": 2 grobs
.
Edición: 1. Detectar automáticamente qué grob es la tabla de leyendas, es decir, no es necesario cambiar nada después de modificar otras partes de la trama. 2. Cambió el cálculo de las diferencias de ancho, ahora el código debería funcionar cuando se tienen dos leyendas, es decir, también en casos más complejos, por ejemplo: