C'è un modo per modificare la spaziatura tra gli elementi della legenda in ggplot2?


120

C'è un modo per modificare la spaziatura tra gli elementi della legenda in ggplot2? Attualmente ho

legend.position ="top" 

che produce automaticamente una legenda orizzontale. Tuttavia, la spaziatura degli elementi è molto ravvicinata e mi chiedo come distanziarli ulteriormente.


Sarebbe utile avere una soluzione attuale a questo ora che optsè ammortizzato.
geoteoria


3
La risposta di Tung, attualmente in fondo a questo thread, ha un aggiornamento di luglio 2018. I bug sono stati corretti e soluzioni alternative come quella nel pastebin sopra non sono più necessarie.
PatrickT

Risposte:


90

ggplot2 v3.0.0pubblicato nel luglio 2018 ha opzioni di lavoro di modificare legend.spacing.x, legend.spacing.ye legend.text.

Esempio: aumentare la spaziatura orizzontale tra le chiavi della legenda

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: se si desidera espandere solo la spaziatura a destra del testo della legenda, utilizzare stringr::str_pad()

Esempio: spostare le etichette dei tasti della legenda in basso e aumentare la spaziatura verticale

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

Esempio: per 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)) 


Per le legende verticali , l'impostazione legend.key.sizeaumenta solo la dimensione delle chiavi della legenda, non lo spazio verticale tra di esse

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

Al fine di aumentare la distanza tra chiavi legenda, modifica della legend-draw.rrichiesta la funzione. Vedi questo numero per maggiori informazioni

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


3
Grazie per averlo fatto notare. Questa è una nuova fantastica funzionalità, ho sempre usato il dirty-fix di @ user2568648, haha!
Tjebo

1
La tua funzione per aumentare la spaziatura verticale tra i tasti della legenda è l'unica soluzione che ho trovato che funziona esattamente come desidero e con facilità d'uso. Grazie!
Docconcoct

69

Penso che l'opzione migliore sia usare guide_legendall'interno di guides:

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

Nota l'uso di default.unit, non è necessario caricare il gridpacchetto.


2
Ciò richiede più voti positivi, le altre risposte sono obsolete.
Brandon Bertelsen

8
Questo può funzionare per le legende orizzontali. Tuttavia, per la mia legenda verticale a destra del grafico, questo aumenta solo l'altezza della chiave, non la spaziatura tra le chiavi. Le mie chiavi della legenda sono ancora molto vicine l'una all'altra.
Muhsin Zahid Ugur

9
Come dice Mushin, questo non coglie il punto, come con altre risposte, se la legenda è VERTICALE allunga i tasti della legenda (ad esempio i segmenti di linea) senza riempire lo spazio tra i tasti.
PatrickT

Funziona bene insieme a geom_line e geom_point.
Niels Holst

45

Una semplice correzione che uso per aggiungere spazio nelle legende orizzontali, aggiungi semplicemente spazi nelle etichette (vedi estratto sotto):

  scale_fill_manual(values=c("red","blue","white"),
                    labels=c("Label of category 1          ",
                             "Label of category 2          ",
                             "Label of category 3"))

13
Questa è l'unica risposta finora che affronta la domanda! Questo potrebbe essere utile in caso di molte voci: scale_fill_manual(values=values, labels=setNames(paste(labels, " "), entries)).
SaschaH

2
Tecnicamente non è molto bello, soprattutto quando devi introdurre quegli spazi nei livelli dei fattori, ma è l'unica soluzione funzionante per questo.
Patrick Bucher

2
Oppure possiamo usare str_pad per rendere la vita un po 'più facile
Tung

37

Ora che optsè deprecato nel ggplot2pacchetto, la funzione themedovrebbe essere usata invece:

library(grid) # for unit()
... + theme(legend.key.height=unit(3,"line"))
... + theme(legend.key.width=unit(3,"line"))

18
Questa soluzione cambia l'altezza / larghezza delle scatole rispetto alla spaziatura tra di loro.
Berk U.

25

Per aggiungere la spaziatura tra le voci in una legenda, regola i margini dell'elemento del tema legend.text.

Per aggiungere 30pt di spazio a destra di ciascuna etichetta della legenda (può essere utile per una legenda orizzontale):

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

Per aggiungere 30pt di spazio a sinistra di ciascuna etichetta di legenda (può essere utile per una legenda verticale):

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

per un ggplot2oggetto p. Le parole chiave sono legend.texte margin.

[Nota sulla modifica: quando questa risposta è stata pubblicata per la prima volta, c'era un bug. Il bug è stato ora risolto]


3
Il bug è stato ora risolto, questa dovrebbe essere la risposta accettata.
giocomai

1
Vedi anche la risposta di Tung per un aggiornamento di luglio 2018 su questi argomenti.
PatrickT

17

Sembra che l'approccio migliore (nel 2018) sia quello di utilizzare legend.key.sizesotto l' themeoggetto. (ad esempio, vedi qui ).

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

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

Questo è davvero facile se stai usando 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)

inserisci qui la descrizione dell'immagine

Tuttavia, altrimenti non funziona così bene (ad esempio, se hai bisogno dello sfondo grigio sul simbolo della legenda):

  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

Si noti che i quadrati bianchi iniziano a bloccare il titolo della legenda (e alla fine il grafico stesso se continuiamo ad aumentare il valore).

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

inserisci qui la descrizione dell'immagine

Non ho ancora trovato una soluzione per risolvere il problema di cui sopra ... Fammi sapere nei commenti se hai un'idea e aggiornerò di conseguenza!

  • Mi chiedo se ci sia un modo per sovrapporre le cose usando $layers...

Rendi legend.keytrasparente:theme(legend.key = element_rect(size = 30,color=alpha("transparent",0)))
ukosteopath

1
questa è stata la risposta più semplice e più facile da usare imo
Blacklivesmatter

14

Dal lavoro di Koshke su ggplot2 e dal suo blog (blog di Koshke )

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

Digita theme_get()nella console per visualizzare altri attributi di legenda modificabili.


12
Grazie per il suggerimento e il collegamento al blog di Koshke! Purtroppo però questo sembra cambiare la dimensione delle scatole ma non la spaziatura tra gli elementi.
overflowname

Potresti essere in grado di "fingere" con qualche tipo di grob sovrapposto. Ma non credo che ci sia un modo per ottenere una spaziatura extra all'interno della leggenda. Questa è l'unica menzione che ho trovato nella mailing list di ggplot2: groups.google.com/forum/?fromgroups#!topic/ggplot2/PhkJpP8zJuM
Brandon Bertelsen

2
Posso usarlo per aumentare la spaziatura tra le leggende con successo. L'uso di numeri negativi ha contribuito a ridurre la spaziatura tra le leggende.
Nova

5

Usa uno di questi

legend.spacing = unit(1,"cm")
legend.spacing.x = unit(1,"cm")
legend.spacing.y = unit(1,"cm")
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.