Existe uma maneira de alterar o espaçamento entre os itens de legenda no ggplot2?

120

Existe uma maneira de alterar o espaçamento entre os itens de legenda no ggplot2? Eu atualmente tenho

legend.position ="top" 

que produz automaticamente uma legenda horizontal. No entanto, o espaçamento dos itens é muito próximo e estou me perguntando como espaçá-los ainda mais.

transbordar
fonte
Seria útil ter uma solução atual para isso agora que optsestá depreciado.
geotheory
Aqui: pastebin.com/NnxMiTeH
PatrickT
3
A resposta de Tung, atualmente no final deste tópico, tem uma atualização de julho de 2018. Bugs foram corrigidos e soluções alternativas como a do pastebin acima não são mais necessárias.
PatrickT

Respostas:

90

ggplot2 v3.0.0lançado em julho 2018 tem opções de trabalho para modificar legend.spacing.x, legend.spacing.ye legend.text.

Exemplo: aumentar o espaçamento horizontal entre as chaves da 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 você deseja apenas expandir o espaçamento à direita do texto da legenda, use stringr::str_pad()

Exemplo: mova os rótulos das teclas de legenda para a parte inferior e aumente o espaçamento 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)) 

Exemplo: 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 legendas verticais , a configuração legend.key.sizeapenas aumenta o tamanho das chaves da legenda, não o espaço vertical entre elas

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 a distância entre as teclas de legenda, legend-draw.ré necessária a modificação da função. Veja este problema para mais informações

# 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
fonte
3
Obrigado por apontar isso. Este é um novo recurso tão bom, eu sempre estava usando a correção suja de @ user2568648, haha!
Tjebo
1
Sua função de aumentar o espaçamento vertical entre as teclas de legenda é a única solução que encontrei que funciona exatamente como desejo e com facilidade de uso. Obrigado!
Docconcoct
69

Acho que a melhor opção é usar guide_legendem guides:

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

Observe o uso de default.unit, sem necessidade de carregar o gridpacote.

desconcertado
fonte
2
Isso precisa de mais votos positivos, as outras respostas estão desatualizadas.
Brandon Bertelsen
8
Isso pode funcionar para legendas horizontais. No entanto, para minha legenda vertical à direita do gráfico, isso apenas aumenta a altura da chave, não o espaçamento entre as chaves. Minhas chaves de legenda ainda estão muito próximas umas das outras.
Muhsin Zahid Ugur
9
Como diz Mushin, isso perde o ponto, como com outras respostas, se a legenda for VERTICAL, ela estica as teclas da legenda (por exemplo, os segmentos de linha) sem preencher o espaço entre as teclas.
PatrickT
Funciona bem junto com geom_line e geom_point.
Niels Holst
45

Uma correção simples que eu uso para adicionar espaço em legendas horizontais, basta adicionar espaços nos rótulos (ver trecho abaixo):

  scale_fill_manual(values=c("red","blue","white"),
                    labels=c("Label of category 1          ",
                             "Label of category 2          ",
                             "Label of category 3"))
user2568648
fonte
13
Esta é a única resposta até agora que trata da questão! Isso pode ser útil em caso de muitas entradas: scale_fill_manual(values=values, labels=setNames(paste(labels, " "), entries)).
SaschaH de
2
Tecnicamente não é muito bom, especialmente quando você tem que introduzir esses espaços em níveis de fator, mas é a única solução de trabalho para.
Patrick Bucher
2
Ou podemos usar str_pad para tornar a vida um pouco mais fácil
Tung
37

Agora que optsestá obsoleto no ggplot2pacote, a função themedeve ser usada em seu lugar:

library(grid) # for unit()
... + theme(legend.key.height=unit(3,"line"))
... + theme(legend.key.width=unit(3,"line"))
Pop
fonte
18
Esta solução altera a altura / largura das caixas em oposição ao espaçamento entre elas.
Berk U.
25

Para adicionar espaçamento entre as entradas em uma legenda, ajuste as margens do elemento do tema legend.text.

Para adicionar 30pt de espaço à direita de cada rótulo de legenda (pode ser útil para uma legenda horizontal):

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

Para adicionar 30pt de espaço à esquerda de cada rótulo de legenda (pode ser útil para uma legenda vertical):

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

para um ggplot2objeto p. As palavras-chave são legend.texte margin.

[Nota sobre a edição: quando esta resposta foi postada pela primeira vez, havia um bug. O bug foi corrigido]

jcb
fonte
3
O bug foi corrigido, esta deve ser a resposta aceita.
giocomai
1
Veja também a resposta de Tung para uma atualização de julho de 2018 sobre esses assuntos.
PatrickT
17

Parece que a melhor abordagem (em 2018) é usar legend.key.sizesob o themeobjeto. (por exemplo, veja aqui ).

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

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

Isso é muito fácil se você estiver 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)

insira a descrição da imagem aqui

No entanto, isso não funciona tão bem de outra forma (por exemplo, se você precisar do fundo cinza no símbolo da 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

Observe que os quadrados brancos começam a bloquear o título da legenda (e, eventualmente, o próprio gráfico, se continuarmos aumentando o valor).

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

insira a descrição da imagem aqui

Ainda não encontrei uma solução alternativa para corrigir o problema acima ... Deixe-me saber nos comentários se você tiver uma ideia e eu atualizarei de acordo!

  • Eu me pergunto se há alguma maneira de reorganizar as coisas usando $layers...
theforestecologist
fonte
Faça o legend.keytransparente:theme(legend.key = element_rect(size = 30,color=alpha("transparent",0)))
ukosteopath
1
esta foi a resposta mais direta e fácil de usar imo
Blacklivesmatter
14

Do trabalho de Koshke no ggplot2 e seu 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

Digite theme_get()no console para ver outros atributos de legenda editáveis.

Brandon Bertelsen
fonte
12
Obrigado pela sugestão e link para o blog do Koshke! Infelizmente, no entanto, isso parece alterar o tamanho das caixas, mas não o espaçamento entre os itens.
sobrevoou em
Você pode ser capaz de "falsificá-lo" com algum tipo de grob de sobreposição. Mas não acho que haja uma maneira de obter espaço extra dentro da lenda. Esta é a única menção que pude encontrar na lista de e-mails do ggplot2: groups.google.com/forum/?fromgroups#!topic/ggplot2/PhkJpP8zJuM
Brandon Bertelsen
2
Posso usar isso para aumentar o espaçamento entre as lendas com sucesso. O uso de números negativos ajudou a diminuir o espaçamento entre as legendas.
Nova de
5

Use qualquer um destes

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