Czy istnieje sposób na zmianę odstępów między elementami legendy w ggplot2?

120

Czy istnieje sposób na zmianę odstępów między elementami legendy w ggplot2? Obecnie mam

legend.position ="top" 

która automatycznie tworzy poziomą legendę. Jednak odstępy między elementami są bardzo małe i zastanawiam się, jak rozmieścić je dalej od siebie.

overflowname
źródło
Przydałoby się mieć aktualne rozwiązanie tego problemu teraz, które optsjest amortyzowane.
geoteoria
Tutaj: pastebin.com/NnxMiTeH
PatrickT
3
Odpowiedź Tunga, obecnie na dole tego wątku, ma aktualizację z lipca 2018 r. Błędy zostały naprawione, a hackerskie obejścia, takie jak to w powyższym pastebin, nie są już potrzebne.
PatrickT,

Odpowiedzi:

90

ggplot2 v3.0.0wydany w lipcu 2018 posiada opcje pracy zmodyfikować legend.spacing.x, legend.spacing.yi legend.text.

Przykład: Zwiększ poziome odstępy między klawiszami legendy

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

Uwaga: jeśli chcesz tylko rozszerzyć odstępy z prawej strony tekstu legendy, użyj stringr::str_pad()

Przykład: Przenieś etykiety klucza legendy na dół i zwiększ odstępy w pionie

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

Przykład: dla 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)) 


W przypadku legend pionowych ustawienie legend.key.sizezwiększa tylko rozmiar kluczy legendy, a nie odstępy między nimi w pionie

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

Aby zwiększyć odległość między klawiszami legendy, legend-draw.rkonieczna jest modyfikacja funkcji. Zobacz ten numer, aby uzyskać więcej informacji

# 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
źródło
3
Dziękuję za zwrócenie uwagi. To jest taka wspaniała nowa funkcja, zawsze używałem dirty-fix @ user2568648, haha!
Tjebo
1
Twoja funkcja zwiększania odstępów w pionie między klawiszami legendy jest jedynym rozwiązaniem, które znalazłem, które działa dokładnie tak, jak chcę i jest łatwe w użyciu. Dzięki!
Docconcoct
69

Myślę, że najlepszą opcją jest użycie guide_legendw guides:

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

Zwróć uwagę na użycie default.unit, nie ma potrzeby ładowania gridpakietu.

agstudy
źródło
2
To wymaga więcej głosów pozytywnych, inne odpowiedzi są nieaktualne.
Brandon Bertelsen
8
Może to działać w przypadku legend poziomych. Jednak w mojej legendzie pionowej po prawej stronie wykresu zwiększa to tylko wysokość klucza, a nie odstępy między klawiszami. Moje klucze legendy są nadal bardzo blisko siebie.
Muhsin Zahid Ugur
9
Jak mówi Mushin, to mija się z celem, podobnie jak w przypadku innych odpowiedzi, jeśli legenda jest PIONOWA , rozciąga klawisze legendy (np. Segmenty linii) bez wypełniania przestrzeni między klawiszami.
PatrickT
Dobrze współpracuje z geom_line i geom_point.
Niels Holst
45

Prosta poprawka, której używam, aby dodać spację w legendach poziomych, po prostu dodaj spacje w etykietach (patrz wyciąg poniżej):

  scale_fill_manual(values=c("red","blue","white"),
                    labels=c("Label of category 1          ",
                             "Label of category 2          ",
                             "Label of category 3"))
user2568648
źródło
13
To jedyna jak dotąd odpowiedź, która dotyczy tego pytania! Może to być pomocne w przypadku wielu wpisów: scale_fill_manual(values=values, labels=setNames(paste(labels, " "), entries)).
SaschaH
2
Technicznie niezbyt ładne, zwłaszcza gdy trzeba wprowadzić te przestrzenie do poziomów współczynników, ale jest to jedyne działające rozwiązanie.
Patrick Bucher
2
Lub możemy użyć str_pad, aby trochę ułatwić życie
Tung,
37

Teraz to optsjest przestarzałe w ggplot2pakiecie, themezamiast tego należy użyć funkcji :

library(grid) # for unit()
... + theme(legend.key.height=unit(3,"line"))
... + theme(legend.key.width=unit(3,"line"))
Muzyka pop
źródło
18
To rozwiązanie zmienia wysokość / szerokość pudełek w przeciwieństwie do odstępów między nimi.
Berk U.
25

Aby dodać odstępy między wpisami w legendzie, dostosuj marginesy elementu motywu legend.text .

Aby dodać 30 punktów miejsca po prawej stronie każdej etykiety legendy (może być przydatne w przypadku legendy poziomej):

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

Aby dodać 30 punktów miejsca po lewej stronie każdej etykiety legendy (może być przydatne w przypadku legendy pionowej):

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

za ggplot2obiekt p. Słowa kluczowe to legend.texti margin.

[Uwaga dotycząca edycji: kiedy ta odpowiedź została opublikowana po raz pierwszy, wystąpił błąd. Błąd został już naprawiony]

jcb
źródło
3
Błąd został już naprawiony, to powinna być zaakceptowana odpowiedź.
giocomai
1
Zobacz także odpowiedź Tunga na aktualizację z lipca 2018 w tych sprawach.
PatrickT
17

Wygląda na to, że najlepszym podejściem (w 2018 roku) jest użycie legend.key.sizepod themeobiektem. (np. patrz tutaj ).

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

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

Jest to naprawdę łatwe, jeśli używasz 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)

wprowadź opis obrazu tutaj

Jednak w przeciwnym razie nie działa to tak dobrze (np. Jeśli potrzebujesz szarego tła na swoim symbolu legendy):

  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

Zwróć uwagę, że białe kwadraty zaczynają blokować tytuł legendy (i ostatecznie sam wykres, jeśli zwiększaliśmy wartość).

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

wprowadź opis obrazu tutaj

Nie do końca znalazłem obejście tego problemu ... Daj mi znać w komentarzach, jeśli masz pomysł, a zaktualizuję odpowiednio!

  • Zastanawiam się, czy istnieje sposób na ponowne nałożenie warstw za pomocą $layers...
leśnik
źródło
Uczyń legend.keyprzejrzystym:theme(legend.key = element_rect(size = 30,color=alpha("transparent",0)))
ukosteopath
1
to była najprostsza odpowiedź i najłatwiejsza w użyciu imo
Blacklivesmatter
14

Z pracy Koshke na ggplot2 i jego blogu (blog Koshke )

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

Wpisz theme_get()w konsoli, aby zobaczyć inne edytowalne atrybuty legendy.

Brandon Bertelsen
źródło
12
Dzięki za sugestię i link do bloga Koshke! Niestety wydaje się, że zmienia to rozmiar pudełek, ale nie odstępy między elementami.
przeleciał
Możesz to „udawać” za pomocą jakiegoś nakładającego się grobu. Ale nie sądzę, aby istniał sposób na uzyskanie dodatkowego odstępu w legendzie. To jedyna wzmianka o tym, jaką udało mi się znaleźć na liście mailingowej ggplot2: groups.google.com/forum/?fromgroups#!topic/ggplot2/PhkJpP8zJuM
Brandon Bertelsen
2
Mogę to wykorzystać, aby skutecznie zwiększyć odstępy między legendami. Użycie liczb ujemnych pomogło zmniejszyć odstępy między legendami.
Nova
5

Użyj dowolnego z nich

legend.spacing = unit(1,"cm")
legend.spacing.x = unit(1,"cm")
legend.spacing.y = unit(1,"cm")
MaazKhan47
źródło