ggplot2: добавление легенды вручную

как я могу map любой (несвязанная) легенда к существующему ggplot?

отказ от ответственности: пожалуйста, не ненавидеть меня. Я знаю, что лучший способ создать легенду с помощью "ggplot2" - правильно сопоставить ваши данные, и я делаю это 99% времени. Здесь, однако, я прошу чего-то, что вообще может дать мне любую легенду, которую я хочу.

в качестве примера у меня есть сюжет, который выглядит примерно так: enter image description here

создать из этого код:

set.seed(42)
temp1 = cbind.data.frame(begin = rnorm(10, 0, 1), end = rnorm(10, 2, 1), y1 = 1:10, y2 = 1:10, id = as.character(1:10))
temp2 = cbind.data.frame(x = 0:2, y = 1:3*2)
temp3 = cbind.data.frame(x = seq(0.5, 1.5, 0.33))
temp = c()
plot1 = ggplot(data = temp, aes(x = x)) + 
  geom_vline(data = temp3, aes(xintercept = x), color = "red", linetype = "longdash") + 
  geom_segment(data = temp1, aes(y = y1, yend = y2, x = begin, xend = end, color = id)) +
  geom_point(data = temp2, aes(x = x, y = y), shape = 4, size = 4) +
  scale_color_discrete(guide = F) 
plot1

и я хочу добавить легенду, которая содержит:

  • красный, longdashed вертикальная линия под названием "Л1"
  • черная сплошная горизонтальная линия под названием "l2"
  • зеленый заполненный блок под названием "l3"

В идеале я бы произвел это примерно так (псевдо-код впереди):

plot2 = plot1 + guide(elements = list(list(type = "line", color = "red", linetype = "longdash", direction = "vertical", label = "l1"), list(type = "line", label = "l2"), list(type = "rect", fill = "green", label = "l3"))

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

еще раз, идея в том, как я могу добавить любую несвязанную легенду к существующему сюжету, т. е. без умного сопоставления исходных данных с переменными сюжета?

1 ответов


легенда может быть построена с нуля: использовать grid для построения элементов легенды; затем использовать gtable для размещения элементов в легенде и легенды в сюжете. Это немного грубо, но дает общее представление.

set.seed(42)
temp1 = cbind.data.frame(begin = rnorm(10, 0, 1), end = rnorm(10, 2, 1), y1 = 1:10, y2 = 1:10, id = as.character(1:10))
temp2 = cbind.data.frame(x = 0:2, y = 1:3*2)
temp3 = cbind.data.frame(x = seq(0.5, 1.5, 0.33))
temp = c()

library(ggplot2)  
library(grid)  
library(gtable)  

plot1 = ggplot(data = temp, aes(x = x)) + 
  geom_vline(data = temp3, aes(xintercept = x), color = "red", linetype = "longdash") + 
  geom_segment(data = temp1, aes(y = y1, yend = y2, x = begin, xend = end, color = id)) +
  geom_point(data = temp2, aes(x = x, y = y), shape = 4, size = 4) +
  scale_color_discrete(guide = F) 


# Construct the six grobs - three symbols and three labels
L1 = linesGrob(x = unit(c(.5, .5), "npc"), y = unit(c(.25, .75), "npc"),
   gp = gpar(col = "red", lty = "longdash"))
L2 = linesGrob(x = unit(c(.25, .75), "npc"), y = unit(c(.5, .5), "npc"))
L3 = rectGrob(height = .5, width = .5, gp = gpar(fill = "green", col = NA))
T1 = textGrob("l1", x = .2, just = "left")
T2 = textGrob("l2", x = .2, just = "left")
T3 = textGrob("l3", x = .2, just = "left")

# Construct a gtable - 2 columns X 4 rows
leg = gtable(width = unit(c(1,1), "cm"), height = unit(c(1,1,1,1), "cm"))
leg = gtable_add_grob(leg, rectGrob(gp = gpar(fill = NA, col = "black")), t=2,l=1,b=4,r=2)

# Place the six grob into the table
leg = gtable_add_grob(leg, L1, t=2, l=1)
leg = gtable_add_grob(leg, L2, t=3, l=1)
leg = gtable_add_grob(leg, L3, t=4, l=1)
leg = gtable_add_grob(leg, T1, t=2, l=2)
leg = gtable_add_grob(leg, T2, t=3, l=2)
leg = gtable_add_grob(leg, T3, t=4, l=2)

# Give it a title (if needed)
leg = gtable_add_grob(leg, textGrob("Legend"), t=1, l=1, r=2)

# Get the ggplot grob for plot1
g = ggplotGrob(plot1)

# Get the position of the panel,
# add a column to the right of the panel, 
# put the legend into that column, 
# and then add another spacing column
pos = g$layout[grepl("panel", g$layout$name), c('t', 'l')]
g = gtable_add_cols(g, sum(leg$widths), pos$l)
g = gtable_add_grob(g, leg, t = pos$t, l = pos$l + 1)
g = gtable_add_cols(g, unit(6, "pt"), pos$l)

# Draw it
grid.newpage()
grid.draw(g)

enter image description here