Есть ли способ изменить интервал между элементами легенды в ggplot2?


120

Есть ли способ изменить интервал между элементами легенды в ggplot2? У меня сейчас есть

legend.position ="top" 

который автоматически создает горизонтальную легенду. Тем не менее, элементы располагаются очень близко друг к другу, и мне интересно, как расположить их дальше друг от друга.


Было бы полезно иметь текущее решение этой проблемы, которое optsуже обесценилось.
geotheory


3
Ответ Тунга, который в настоящее время находится внизу этой ветки, содержит обновление за июль 2018 года. Ошибки были исправлены, и более не нужны хитрые обходные пути, подобные описанному выше в pastebin.
PatrickT

Ответы:


90

ggplot2 v3.0.0выпущенный в июле 2018 года, есть рабочие параметры, которые нужно изменить legend.spacing.x, legend.spacing.yи legend.text.

Пример: увеличить горизонтальный интервал между клавишами легенды

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

Примечание. Если вы хотите расширить интервал только справа от текста легенды, используйте stringr::str_pad()

Пример: переместите подписи клавиш легенды вниз и увеличьте интервал по вертикали.

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

Пример: для 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)) 


Для вертикальных легенд настройка legend.key.sizeувеличивает только размер клавиш легенды, а не вертикальное пространство между ними.

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

Чтобы увеличить расстояние между клавишами легенды, необходимо изменить legend-draw.rфункцию. См. Этот выпуск для получения дополнительной информации

# 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
Спасибо за указание на это. Это такая замечательная новая функция, я всегда использовал грязное исправление @ user2568648, ха-ха!
Tjebo

1
Ваша функция увеличения вертикального расстояния между клавишами легенды - единственное решение, которое я нашел, которое работает именно так, как я хочу, и с легкостью использования. Спасибо!
Docconcoct

69

Думаю, что лучше всего использовать guide_legendвнутри guides:

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

Обратите внимание на использование default.unit, нет необходимости загрузки gridпакета.


2
Для этого нужно больше голосов, другие ответы устарели.
Брэндон Бертельсен

8
Это может работать для горизонтальных легенд. Однако для моей вертикальной легенды справа от графика это увеличивает только высоту клавиши, а не расстояние между клавишами. Мои ключи легенды все еще очень близки друг к другу.
Мухсин Захид Угур

9
Как говорит Мушин, это не соответствует сути, как и в случае с другими ответами, если легенда ВЕРТИКАЛЬНА, она растягивает клавиши легенды (например, сегменты линии) без заполнения пространства между клавишами.
PatrickT

Прекрасно работает вместе с geom_line и geom_point.
Нильс Холст,

45

Простое исправление, которое я использую для добавления пробелов в горизонтальные легенды, просто добавляйте пробелы в метках (см. Отрывок ниже):

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

13
На данный момент это единственный ответ, касающийся данного вопроса! Это может быть полезно в случае многих записей: scale_fill_manual(values=values, labels=setNames(paste(labels, " "), entries)).
SaschaH

2
Технически не очень хорошо, особенно когда вам нужно ввести эти пробелы в уровни факторов, но это единственное рабочее решение для этого.
Патрик Бучер,

2
Или мы можем использовать str_pad, чтобы немного облегчить жизнь
Тунг

37

Теперь, когда optsэто не рекомендуется в ggplot2пакете, themeвместо него следует использовать функцию :

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

18
Это решение изменяет высоту / ширину ящиков, а не расстояние между ними.
Berk U.

25

Чтобы добавить интервал между записями в легенде, настройте поля элемента темы legend.text.

Чтобы добавить 30pt места справа от каждой подписи легенды (может быть полезно для горизонтальной легенды):

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

Чтобы добавить 30pt места слева от каждой подписи (может быть полезно для вертикальной легенды):

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

для ggplot2объекта p. Ключевые слова: legend.textи margin.

[Примечание об изменении: когда этот ответ был впервые опубликован, произошла ошибка. Ошибка исправлена]


3
Теперь ошибка исправлена, это должен быть принятый ответ.
giocomai

1
См. Также ответ Тунга на обновленную информацию по этим вопросам за июль 2018 года.
PatrickT

17

Похоже, лучший подход (в 2018 году) - использовать legend.key.sizeпод themeобъектом. (например, см. здесь ).

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

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

Это очень просто, если вы используете 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)

введите описание изображения здесь

Однако в противном случае это работает не так хорошо (например, если вам нужен серый фон на вашем символе легенды):

  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

Обратите внимание, что белые квадраты начинают блокировать заголовок легенды (и, в конечном итоге, сам график, если мы продолжаем увеличивать значение).

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

введите описание изображения здесь

Я не совсем нашел способ решения вышеуказанной проблемы ... Дайте мне знать в комментариях, если у вас есть идея, и я соответствующим образом обновлю!

  • Интересно, есть ли способ переслоить вещи, используя $layers...

Сделайте legend.keyпрозрачное:theme(legend.key = element_rect(size = 30,color=alpha("transparent",0)))
укостеопат

1
это был самый простой ответ и самый простой в использовании имо
Blacklivesmatter

14

Из работы Кошке над ggplot2 и его блога (блог Кошке )

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

Введите theme_get()в консоли, чтобы увидеть другие редактируемые атрибуты легенды.


12
Спасибо за предложение и ссылку на блог Кошке! К сожалению, похоже, что это изменит размер ящиков, но не расстояние между элементами.
overflowname

Вы можете «подделать» его с помощью какого-нибудь наложенного гроба. Но я не думаю, что есть способ получить дополнительный интервал внутри легенды. Это единственное упоминание об этом, которое я смог найти в списке рассылки ggplot2
Брэндон Бертельсен

2
Я могу использовать это, чтобы успешно увеличить интервал между легендами. Использование отрицательных чисел помогло уменьшить интервалы между легендами.
Нова

5

Используйте любой из этих

legend.spacing = unit(1,"cm")
legend.spacing.x = unit(1,"cm")
legend.spacing.y = unit(1,"cm")
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.