2016-01-16 20 views
6

Jak mogę mapować dowolną legendę (niepowiązaną) na istniejący ggplot?ggplot2: ręcznie dodaj legendę

Nota prawna: proszę, nie nienawidź mnie. Wiem, że najlepszym sposobem utworzenia legendy z "ggplot2" jest mapowanie danych w odpowiedni sposób i robię to w 99% przypadków. Tutaj jednak proszę o coś, co generalnie może dać mi jakąkolwiek legendę, której pragnę.

Jako przykład mam działkę, która wygląda nieco jak poniżej: enter image description here

stworzony z tego kodu:

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 

i chcę dodać legendę, która zawiera:

  • czerwona, długa linia pionowa o nazwie "l1"
  • czarna, solidna linia pozioma o nazwie "l2"
  • blok zielony wypełnione nazwie „L3”

idealnie chciałbym produkować że trochę tak (pseudo-kod naprzód):

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

moim najlepszym zgadywać, jak podejść do tego byłoby stworzenie niektóre pomocnicze pseudo-dane, które zostały naniesione/odwzorowane gdzieś niewidocznie na wykresie, a następnie użyte do stworzenia legendy, ale nie udało mi się uzyskać czegoś takiego, aby narysować mi legendę.

Po raz kolejny chodzi o to, w jaki sposób dodać niepowiązaną legendę do istniejącego wykresu, tj. Bez sprytnego odwzorowania oryginalnych danych na zmienne fabuły?

+0

Można ręcznie skonstruować coś używając 'geom_text' i' geom_line'. –

+0

Lub ręcznie dodaj coś za pomocą 'grid' i grobs. Lub spróbuj wypisać rozszerzenie do ggplot2, aby to zrobić. Wyobrażam sobie, że ktoś w końcu to zrobi, ponieważ podobne pytania pojawiają się bardzo często. –

+0

Można "oszukiwać" i dodawać wypełnienie, które nie pojawi się na działce, a następnie użyć redagowania do edycji, ale podoba ci się etykieta wypełniająca. – user5029763

Odpowiedz

3

Legenda może być skonstruowana od zera: użyj grid do skonstruowania elementów legendy; następnie użyj gtable, aby umieścić elementy w legendzie i legendę na wykresie. Jest to trochę surowe, ale daje ogólny pogląd.

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

+0

To jest orzechy! Ale dzięki za pokazanie, jak to zrobić w tak jasny sposób. – bdemarest

Powiązane problemy