Apakah ada cara untuk mengubah jarak antar item legenda di ggplot2?

120

Apakah ada cara untuk mengubah jarak antar item legenda di ggplot2? Saya saat ini punya

legend.position ="top" 

yang secara otomatis menghasilkan legenda horizontal. Namun, jarak item sangat berdekatan dan saya bertanya-tanya bagaimana cara memberi jarak yang lebih jauh.

overflowname
sumber
Akan berguna untuk memiliki solusi saat ini untuk sekarang yang optsdisusutkan.
geotheory
Di sini: pastebin.com/NnxMiTeH
PatrickT
3
Jawaban Tung, saat ini di bagian bawah utas ini, memiliki pembaruan Juli 2018. Bug telah diperbaiki dan solusi hacky seperti yang ada di pastebin di atas tidak lagi diperlukan.
PatrickT

Jawaban:

90

ggplot2 v3.0.0dirilis pada Juli 2018 memiliki opsi kerja untuk dimodifikasi legend.spacing.x, legend.spacing.ydan legend.text.

Contoh: Meningkatkan jarak horizontal antara tombol 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'))

Catatan: Jika Anda hanya ingin memperluas penspasian di sebelah kanan teks legenda, gunakan stringr::str_pad()

Contoh: Pindahkan label kunci legenda ke bawah dan tambah jarak vertikal

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

Contoh: untuk 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)) 


Untuk legenda vertikal , pengaturan legend.key.sizehanya meningkatkan ukuran tombol legenda, bukan spasi vertikal di antara mereka

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

Untuk menambah jarak antar tombol legenda, diperlukan modifikasi legend-draw.rfungsi. Lihat masalah ini untuk info lebih lanjut

# 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
sumber
3
Terima kasih telah menunjukkan hal ini. Ini adalah fitur baru yang luar biasa, saya selalu menggunakan perbaikan kotor @ user2568648, haha!
Tjebo
1
Fungsi Anda untuk meningkatkan jarak vertikal antara tombol legenda adalah satu-satunya solusi yang saya temukan yang bekerja persis seperti yang saya inginkan dan dengan kemudahan penggunaan. Terima kasih!
Docconcoct
69

Menurut saya opsi terbaik adalah menggunakan guide_legenddalam guides:

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

Perhatikan penggunaan default.unit, tidak perlu memuat gridpaket.

agstudy
sumber
2
Ini membutuhkan lebih banyak suara positif, jawaban lainnya sudah usang.
Brandon Bertelsen
8
Ini mungkin berhasil untuk legenda horizontal. Namun, untuk legenda vertikal saya di sebelah kanan plot, ini hanya menambah tinggi kunci, bukan jarak antar tombol. Kunci legenda saya masih sangat dekat satu sama lain.
Muhsin Zahid Ugur
9
Seperti yang dikatakan Mushin, ini melenceng, seperti halnya jawaban lain, jika legenda itu VERTIKAL, ia meregangkan kunci legenda (misalnya segmen garis) tanpa memberi spasi di antara tombol-tombol.
PatrickT
Bekerja sama dengan baik dengan geom_line dan geom_point.
Niels Holst
45

Perbaikan sederhana yang saya gunakan untuk menambahkan spasi di legenda horizontal, cukup tambahkan spasi di label (lihat ekstrak di bawah):

  scale_fill_manual(values=c("red","blue","white"),
                    labels=c("Label of category 1          ",
                             "Label of category 2          ",
                             "Label of category 3"))
pengguna2568648
sumber
13
Sejauh ini, ini adalah satu-satunya jawaban yang berhubungan dengan pertanyaan tersebut! Ini mungkin bisa membantu dalam hal banyak entri: scale_fill_manual(values=values, labels=setNames(paste(labels, " "), entries)).
SaschaH
2
Secara teknis tidak terlalu bagus, terutama ketika Anda harus memasukkan ruang-ruang itu ke dalam level faktor, tetapi itu satu-satunya solusi yang berfungsi.
Patrick Bucher
2
Atau kita dapat menggunakan str_pad untuk membuat hidup sedikit lebih mudah
Tung
37

Sekarang yang optstidak digunakan lagi dalam ggplot2paket, fungsi themeharus digunakan sebagai gantinya:

library(grid) # for unit()
... + theme(legend.key.height=unit(3,"line"))
... + theme(legend.key.width=unit(3,"line"))
Pop
sumber
18
Solusi ini mengubah tinggi / lebar kotak sebagai lawan dari jarak di antara mereka.
Berk U.
25

Untuk menambahkan spasi antar entri dalam legenda, sesuaikan margin elemen tema legend.text.

Untuk menambahkan ruang 30pt di sebelah kanan setiap label legenda (mungkin berguna untuk legenda horizontal):

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

Untuk menambahkan ruang 30pt di sebelah kiri setiap label legenda (mungkin berguna untuk legenda vertikal):

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

untuk sebuah ggplot2objek p. Kata kuncinya adalah legend.textdanmargin .

[Catatan tentang edit: Saat jawaban ini pertama kali diposting, ada bug. Bug sekarang telah diperbaiki]

jcb
sumber
3
Bug sekarang telah diperbaiki, ini harus menjadi jawaban yang diterima.
giocomai
1
Lihat juga jawaban Tung untuk update Juli 2018 tentang masalah ini.
PatrickT
17

Sepertinya pendekatan terbaik (pada 2018) adalah menggunakan objek legend.key.sizedi bawah theme. (misalnya, lihat di sini ).

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

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

Ini sangat mudah jika Anda menggunakantheme_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)

masukkan deskripsi gambar di sini

Namun, ini tidak bekerja dengan baik jika tidak (misalnya, jika Anda memerlukan latar belakang abu-abu pada simbol legenda Anda):

  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

Perhatikan bahwa kotak putih mulai memblokir judul legenda (dan akhirnya grafik itu sendiri jika kita terus meningkatkan nilainya).

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

masukkan deskripsi gambar di sini

Saya belum menemukan solusi untuk memperbaiki masalah di atas ... Beri tahu saya di komentar jika Anda punya ide, dan saya akan memperbaruinya sesuai dengan itu!

  • Saya ingin tahu apakah ada cara untuk melapisi ulang hal-hal menggunakan $layers...
ahli kehutanan
sumber
Buat legend.keytransparan:theme(legend.key = element_rect(size = 30,color=alpha("transparent",0)))
ukosteopath
1
ini adalah jawaban yang paling mudah dan paling mudah digunakan imo
Blacklivesmatter
14

Dari karya Koshke di ggplot2 dan blognya (blog Koshke )

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

Ketik theme_get()di konsol untuk melihat atribut legenda lainnya yang dapat diedit.

Brandon Bertelsen
sumber
12
Terima kasih atas saran dan tautan ke blog Koshke! Sayangnya, hal ini tampaknya mengubah ukuran kotak tetapi tidak mengubah jarak antar item.
overflowname
Anda mungkin bisa "memalsukannya" dengan semacam grob overlay. Tapi saya rasa tidak ada cara untuk mendapatkan jarak ekstra di dalam legenda. Ini adalah satu-satunya penyebutan yang dapat saya temukan di milis ggplot2: groups.google.com/forum/?fromgroups#!topic/ggplot2/PhkJpP8zJuM
Brandon Bertelsen
2
Saya dapat menggunakan ini untuk meningkatkan jarak antar legenda dengan sukses. Menggunakan angka negatif membantu mengurangi jarak antar legenda.
Nova
5

Gunakan salah satu dari ini

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