¿Hay alguna forma de cambiar el espacio entre los elementos de la leyenda en ggplot2?

120

¿Hay alguna forma de cambiar el espacio entre los elementos de la leyenda en ggplot2? Actualmente tengo

legend.position ="top" 

que produce automáticamente una leyenda horizontal. Sin embargo, el espaciado de los elementos está muy cerca y me pregunto cómo espaciarlos más.

overflowname
fuente
Sería útil tener una solución actual para esto ahora que optsestá depreciado.
Geoteoría
Aquí: pastebin.com/NnxMiTeH
PatrickT
3
La respuesta de Tung, actualmente al final de este hilo, tiene una actualización de julio de 2018. Los errores se han corregido y ya no se necesitan soluciones pirateadas como la del pastebin anterior.
PatrickT

Respuestas:

90

ggplot2 v3.0.0publicado en julio de 2018 tiene opciones de trabajo para modificar legend.spacing.x, legend.spacing.yy legend.text.

Ejemplo: aumentar el espacio horizontal entre las claves de leyenda

library(ggplot2)

ggplot(mtcars, aes(factor(cyl), fill = factor(cyl))) + 
  geom_bar() +
  coord_flip() +
  scale_fill_brewer("Cyl", palette = "Dark2") +
  theme_minimal(base_size = 14) +
  theme(legend.position = 'top', 
        legend.spacing.x = unit(1.0, 'cm'))

Nota: Si solo desea expandir el espaciado a la derecha del texto de la leyenda, use stringr::str_pad()

Ejemplo: mueva las etiquetas de las teclas de leyenda hacia la parte inferior y aumente el espaciado vertical

ggplot(mtcars, aes(factor(cyl), fill = factor(cyl))) + 
  geom_bar() +
  coord_flip() +
  scale_fill_brewer("Cyl", palette = "Dark2") +
  theme_minimal(base_size = 14) +
  theme(legend.position = 'top', 
        legend.spacing.x = unit(1.0, 'cm'),
        legend.text = element_text(margin = margin(t = 10))) +
  guides(fill = guide_legend(title = "Cyl",
                             label.position = "bottom",
                             title.position = "left", title.vjust = 1)) 

Ejemplo: para scale_fill_xxx&guide_colorbar

ggplot(mtcars, aes(mpg, wt)) +
  geom_point(aes(fill = hp), pch = I(21), size = 5)+
  scale_fill_viridis_c(guide = FALSE) +
  theme_classic(base_size = 14) +
  theme(legend.position = 'top', 
        legend.spacing.x = unit(0.5, 'cm'),
        legend.text = element_text(margin = margin(t = 10))) +
  guides(fill = guide_colorbar(title = "HP",
                               label.position = "bottom",
                               title.position = "left", title.vjust = 1,
                               # draw border around the legend
                               frame.colour = "black",
                               barwidth = 15,
                               barheight = 1.5)) 


Para las leyendas verticales , la configuración legend.key.sizesolo aumenta el tamaño de las claves de leyenda, no el espacio vertical entre ellas

ggplot(mtcars) +
  aes(x = cyl, fill = factor(cyl)) +
  geom_bar() +
  scale_fill_brewer("Cyl", palette = "Dark2") +
  theme_minimal(base_size = 14) +
  theme(legend.key.size = unit(1, "cm"))

Para aumentar la distancia entre las teclas de leyenda, legend-draw.res necesario modificar la función. Consulte este número para obtener más información.

# function to increase vertical spacing between legend keys
# @clauswilke
draw_key_polygon3 <- function(data, params, size) {
  lwd <- min(data$size, min(size) / 4)

  grid::rectGrob(
    width = grid::unit(0.6, "npc"),
    height = grid::unit(0.6, "npc"),
    gp = grid::gpar(
      col = data$colour,
      fill = alpha(data$fill, data$alpha),
      lty = data$linetype,
      lwd = lwd * .pt,
      linejoin = "mitre"
    ))
}

# register new key drawing function, 
# the effect is global & persistent throughout the R session
GeomBar$draw_key = draw_key_polygon3

ggplot(mtcars) +
  aes(x = cyl, fill = factor(cyl)) +
  geom_bar() +
  scale_fill_brewer("Cyl", palette = "Dark2") +
  theme_minimal(base_size = 14) +
  theme(legend.key = element_rect(color = NA, fill = NA),
        legend.key.size = unit(1.5, "cm")) +
  theme(legend.title.align = 0.5)

Tung
fuente
3
Gracias por señalar esto. Esta es una característica nueva tan genial, siempre estaba usando el arreglo sucio de @ user2568648, ¡jaja!
Tjebo
1
Su función para aumentar el espacio vertical entre las teclas de leyenda es la única solución que he encontrado que funciona exactamente como deseo y con facilidad de uso. ¡Gracias!
Docconcoct
69

Creo que la mejor opción es usar guide_legenddentro de guides:

p + guides(fill=guide_legend(
                 keywidth=0.1,
                 keyheight=0.1,
                 default.unit="inch")
      )

Tenga en cuenta el uso de default.unit, no es necesario cargar el gridpaquete.

un estudio
fuente
2
Esto necesita más votos a favor, las otras respuestas están desactualizadas.
Brandon Bertelsen
8
Esto puede funcionar para leyendas horizontales. Sin embargo, para mi leyenda vertical a la derecha del gráfico, esto solo aumenta la altura de la clave, no el espacio entre las teclas. Mis claves de leyenda todavía están muy cerca unas de otras.
Muhsin Zahid Ugur
9
Como dice Mushin, esto pierde el punto, como con otras respuestas, si la leyenda es VERTICAL , estira las claves de la leyenda (por ejemplo, los segmentos de línea) sin rellenar el espacio entre las claves.
PatrickT
Funciona muy bien junto con geom_line y geom_point.
Niels Holst
45

Una solución simple que utilizo para agregar espacio en leyendas horizontales, simplemente agregue espacios en las etiquetas (vea el extracto a continuación):

  scale_fill_manual(values=c("red","blue","white"),
                    labels=c("Label of category 1          ",
                             "Label of category 2          ",
                             "Label of category 3"))
usuario2568648
fuente
13
¡Hasta ahora esta es la única respuesta que se ocupa de la pregunta! Esto podría ser útil en el caso de muchas entradas: scale_fill_manual(values=values, labels=setNames(paste(labels, " "), entries)).
SaschaH
2
Técnicamente no es muy agradable, especialmente cuando tienes que introducir esos espacios en niveles de factor, pero es la única solución que funciona.
Patrick Bucher
2
O podemos usar str_pad para hacer la vida un poco más fácil
Tung
37

Ahora que optsestá obsoleto en el ggplot2paquete, la función themedebe usarse en su lugar:

library(grid) # for unit()
... + theme(legend.key.height=unit(3,"line"))
... + theme(legend.key.width=unit(3,"line"))
Popular
fuente
18
Esta solución cambia la altura / ancho de las cajas en contraposición al espaciado entre ellas.
Berk
25

Para agregar espacio entre las entradas en una leyenda, ajuste los márgenes del elemento del tema legend.text.

Para agregar 30 puntos de espacio a la derecha de cada etiqueta de leyenda (puede ser útil para una leyenda horizontal):

p + theme(legend.text = element_text(
    margin = margin(r = 30, unit = "pt")))

Para agregar 30 puntos de espacio a la izquierda de cada etiqueta de leyenda (puede ser útil para una leyenda vertical):

p + theme(legend.text = element_text(
    margin = margin(l = 30, unit = "pt")))

por un ggplot2objeto p. Las palabras clave son legend.texty margin.

[Nota sobre la edición: cuando se publicó esta respuesta por primera vez, hubo un error. El error ahora se ha solucionado]

jcb
fuente
3
El error ahora se ha corregido, esta debería ser la respuesta aceptada.
giocomai
1
Consulte también la respuesta de Tung para una actualización de julio de 2018 sobre estos asuntos.
PatrickT
17

Parece que el mejor enfoque (en 2018) es usar legend.key.sizedebajo del themeobjeto. (por ejemplo, ver aquí ).

#Set-up:
    library(ggplot2)
    library(gridExtra)

    gp <- ggplot(data = mtcars, aes(mpg, cyl, colour = factor(cyl))) +
        geom_point()

Esto es muy fácil si está utilizando theme_bw():

  gpbw <- gp + theme_bw()

#Change spacing size:

  g1bw <- gpbw + theme(legend.key.size = unit(0, 'lines'))
  g2bw <- gpbw + theme(legend.key.size = unit(1.5, 'lines'))
  g3bw <- gpbw + theme(legend.key.size = unit(3, 'lines'))

  grid.arrange(g1bw,g2bw,g3bw,nrow=3)

ingrese la descripción de la imagen aquí

Sin embargo, esto no funciona tan bien de otra manera (por ejemplo, si necesita el fondo gris en su símbolo de leyenda):

  g1 <- gp + theme(legend.key.size = unit(0, 'lines'))
  g2 <- gp + theme(legend.key.size = unit(1.5, 'lines'))
  g3 <- gp + theme(legend.key.size = unit(3, 'lines'))

  grid.arrange(g1,g2,g3,nrow=3)

#Notice that the legend symbol squares get bigger (that's what legend.key.size does). 

#Let's [indirectly] "control" that, too:
  gp2 <- g3
  g4 <- gp2 + theme(legend.key = element_rect(size = 1))
  g5 <- gp2 + theme(legend.key = element_rect(size = 3))
  g6 <- gp2 + theme(legend.key = element_rect(size = 10))

  grid.arrange(g4,g5,g6,nrow=3)   #see picture below, left

Observe que los cuadrados blancos comienzan a bloquear el título de la leyenda (y eventualmente el gráfico en sí mismo si seguimos aumentando el valor).

  #This shows you why:
    gt <- gp2 + theme(legend.key = element_rect(size = 10,color = 'yellow' ))

ingrese la descripción de la imagen aquí

No he encontrado una solución para solucionar el problema anterior ... ¡Avísame en los comentarios si tienes una idea y la actualizaré en consecuencia!

  • Me pregunto si hay alguna forma de volver a colocar las cosas usando $layers...
el forestecólogo
fuente
Haz lo legend.keytransparente:theme(legend.key = element_rect(size = 30,color=alpha("transparent",0)))
ukosteópata
1
esta fue la respuesta más sencilla y más fácil de usar imo
Blacklivesmatter
14

Del trabajo de Koshke en ggplot2 y su blog (blog de Koshke )

... + theme(legend.key.height=unit(3,"line")) # Change 3 to X
... + theme(legend.key.width=unit(3,"line")) # Change 3 to X

Escriba theme_get()en la consola para ver otros atributos de leyenda editables.

Brandon Bertelsen
fuente
12
¡Gracias por la sugerencia y el enlace al blog de Koshke! Desafortunadamente, sin embargo, esto parece cambiar el tamaño de las cajas pero no el espacio entre los elementos.
overflowname
Es posible que pueda "fingir" con algún tipo de grob superpuesto. Pero no creo que haya una manera de conseguir un espacio extra dentro de la leyenda. Esta es la única mención que pude encontrar en la lista de correo de ggplot2
Brandon Bertelsen
2
Puedo usar esto para aumentar el espacio entre leyendas con éxito. El uso de números negativos ayudó a disminuir el espacio entre leyendas.
Nova
5

Utilice cualquiera de estos

legend.spacing = unit(1,"cm")
legend.spacing.x = unit(1,"cm")
legend.spacing.y = unit(1,"cm")
MaazKhan47
fuente