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.