2010-09-27 20 views
14

Przepraszamy za niewymienione żadne przykładowe dane dotyczące mojego problemu. Nie mogłem znaleźć sposobu na łatwe utworzenie przykładowego pliku kształtu. Mamy nadzieję, że doświadczeni użytkownicy z ggplot mogą zobaczyć, co chciałbym zrobić z poniższego opisu.Różne legendy i kolory wypełnienia dla fasetowanego ggplota?

mam:

  • data.frame X z informacjami o powierzchni próbnych (plotid, var1, var2, var3, var4 ...)

  • Wielokąt shapefile Y z informacji przestrzennej dla powierzchnie próbne

Importowanie kształtu pliku Y (z maptools) i fortify jako data.frameZ (ggplot2) działa poprawnie. melt ing X do X_melted działa równie dobrze. merge -ing Z i X_melted do mapdf działa również.

Oznacza to, że teraz mamy data.frame w długiej formie z informacji przestrzennej i var1, var2, var3 ...

Teraz chcę wykreślić tę ramkę danych takiego:

pl1 <- ggplot(mapdf,aes(long,lat),group=group) 
pl1 <- pl1 + geom_polygon(aes(group=group,fill=value),colour="black") 
pl1 <- pl1 + facet_grid(variable ~ .) 
pl1 <- pl1 + coord_equal(ratio = 1) 
pl1 

Wynik jest ładną fabułą z jednym panelem dla każdej zmiennej. Mapy paneli są identyczne, ale kolor wypełnienia zależy od wartości zmiennych. Do tej pory wszystko działa jak urok ... z jednym problemem:

Zmienne mają różne wartości min i maksimum. Na przykład var1 idzie z 0 do 5, var2 z 0 do 400, var3 z 5 do 10 itp w tym przykładzie, legenda dla koloru wypełnienia idzie z 0 do 400. var2 jest ładnie narysowany, ale var1 i var3 są w zasadzie w tym samym kolorze.

Czy istnieje sposób, w jaki mogę użyć innej legendy dla każdego panelu aspektu? Czy jest to po prostu niemożliwe (jeszcze) z facet_wrap lub facet_grid w ggplot?

Potrafię tworzyć indywidualne wykresy dla każdej zmiennej i łączyć je z rzutniami, ale jest tam mnóstwo zmiennych i będzie to wymagało wiele pracy.

A może jest inny pakiet lub metoda, której mógłbym użyć, aby osiągnąć to, co chcę zrobić?

Pomoc byłaby bardzo ceniona.:)

Edit: Z pomocą ggplot2 -package opisem, budowałem przykład, który ilustruje mój problem:

ids <- factor(c("1.1", "2.1", "1.2", "2.2", "1.3", "2.3")) 
values <- data.frame(
id = ids, 
val1 = cumsum(runif(6, max = 0.5)), 
val2 = cumsum(runif(6, max = 50)) 
) 
positions <- data.frame(
id = rep(ids, each = 4), 
x = c(2, 1, 1.1, 2.2, 1, 0, 0.3, 1.1, 2.2, 1.1, 1.2, 2.5, 1.1, 0.3, 
0.5, 1.2, 2.5, 1.2, 1.3, 2.7, 1.2, 0.5, 0.6, 1.3), 
y = c(-0.5, 0, 1, 0.5, 0, 0.5, 1.5, 1, 0.5, 1, 2.1, 1.7, 1, 1.5, 
2.2, 2.1, 1.7, 2.1, 3.2, 2.8, 2.1, 2.2, 3.3, 3.2) 
) 

values <- melt(values) 
datapoly <- merge(values, positions, by=c("id")) 

p <- ggplot(datapoly, aes(x=x, y=y)) + geom_polygon(aes(fill=value, group=id),colour="black") 
p <- p + facet_wrap(~ variable) 
p 

panel po prawej stronie ilustruje różne wartości dla var2 na mapie. Na panelu po lewej jednak wszystkie wielokąty mają ten sam kolor. Jest to logiczne, ponieważ dla wszystkich paneli stosowany jest tylko jeden gradient kolorów. Czy mogę użyć innego gradientu kolorów dla każdego panelu?

Odpowiedz

13

Obecnie może istnieć tylko jedna skala na działkę (dla wszystkiego oprócz x i y).

+1

OK, dziękuję za odpowiedź. Czy ta funkcja może zostać zaimplementowana w najbliższym czasie? ;) – donodarazao

+1

Jest to bardzo mało prawdopodobne, ponieważ można łatwo obejść rysując oddzielne wątki. – hadley

1

Być może trochę niekonwencjonalne, ale możesz spróbować faktoringu swojej "wartości". Na przykład:

p <- ggplot(datapoly, aes(x=x, y=y)) + geom_polygon(aes(fill=factor(value), group=id),colour="black") 
p <- p + facet_wrap(~ variable) 
p 

ggplot2 wykorzystuje czynniki do tworzenia legend. Jeśli więc możesz dodać kolumnę, która przyjmuje "wartość" i dzieli ją na przedziały, możesz zastąpić "wartość" zakresami.

Utwórz kolumnę, jak "f":

id variable  value x y f 
1 1.1  val1 0.09838607 2.0 -0.5 0.09-0.13 
2 1.1  val1 0.09838607 1.0 0.0 0.09-0.13 
3 1.1  val1 0.09838607 1.1 1.0 0.09-0.13 
4 1.1  val1 0.09838607 2.2 0.5 0.09-0.13 
25 2.1  val1 0.13121347 1.0 0.0 0.13-0.20 

...

Następnie użyj:

p <- ggplot(datapoly, aes(x=x, y=y)) + geom_polygon(aes(fill=f, group=id),colour="black") 
p <- p + facet_wrap(~ variable) 
p 

Trzeba by określić kategorie, które mają, co może być czasochłonne. Ale przynajmniej wykres wyłoni się, jak tego chcesz. Zasadniczo przekodowałbyś dane do innej kolumny. Oto kilka przykładów:

http://www.statmethods.net/management/variables.html

+0

Dzięki za odpowiedź. Ustawienie wolnej przestrzeni i skal nie pomaga, ponieważ zmienia tylko oś X i Y, ale nie kodowanie kolorami. Zmieniłem moje pytanie, które ma teraz przykład. – donodarazao

+0

Odpowiedź zaktualizowana z aktualizacją pytania. HTH! –

+0

I, nie sądzę, że możliwe jest posiadanie więcej niż jednej legendy w facet_grid. –

1

Na ryzyko rzeczy oczywiste wydaje się, że powinno być kolorowania przez procentach zamiast wartości surowców. Wtedy twoje przekształcone wartości i twoja legenda idą od 0 do 1.

+1

Korzystanie z procentów może być rozwiązaniem, ale niektóre informacje zostaną oczywiście utracone. Wyobraź sobie na przykład var1 = temperatura (od 15 do 20 stopni) i var2 = rel. wilgotność (od 50 do 80%). Wartości procentowe nie byłyby bardzo jasne dla temperatury i dość mylące dla rel. wilgotność (procent procentowy). ;) – donodarazao

3

z siatką dobroci

align.plots <- function(..., vertical=TRUE){ 
#http://ggextra.googlecode.com/svn/trunk/R/align.r 
    dots <- list(...) 
    dots <- lapply(dots, ggplotGrob) 
    ytitles <- lapply(dots, function(.g) editGrob(getGrob(.g,"axis.title.y.text",grep=TRUE), vp=NULL)) 
    ylabels <- lapply(dots, function(.g) editGrob(getGrob(.g,"axis.text.y.text",grep=TRUE), vp=NULL)) 
    legends <- lapply(dots, function(.g) if(!is.null(.g$children$legends)) 
        editGrob(.g$children$legends, vp=NULL) else ggplot2:::.zeroGrob) 

    gl <- grid.layout(nrow=length(dots)) 
    vp <- viewport(layout=gl) 
    pushViewport(vp) 
    widths.left <- mapply(`+`, e1=lapply(ytitles, grobWidth), 
         e2= lapply(ylabels, grobWidth), SIMPLIFY=F) 
    widths.right <- lapply(legends, function(g) grobWidth(g) + if(is.zero(g)) unit(0, "lines") else unit(0.5, "lines")) # safe margin recently added to ggplot2 
    widths.left.max <- max(do.call(unit.c, widths.left)) 
    widths.right.max <- max(do.call(unit.c, widths.right)) 

    for(ii in seq_along(dots)){ 
    pushViewport(viewport(layout.pos.row=ii)) 
    pushViewport(viewport(x=unit(0, "npc") + widths.left.max - widths.left[[ii]], 
          width=unit(1, "npc") - widths.left.max + widths.left[[ii]] - 
               widths.right.max + widths.right[[ii]], 
          just="left")) 
    grid.draw(dots[[ii]]) 
    upViewport(2) 
    } 
} 



p <- ggplot(datapoly[datapoly$variable=="val1",], aes(x=x, y=y)) + geom_polygon(aes(fill=value, group=id),colour="black") 
p1 <- ggplot(datapoly[datapoly$variable=="val2",], aes(x=x, y=y)) + geom_polygon(aes(fill=value, group=id),colour="black") 
align.plots(p,p1) 
+0

+1, mogę z tego skorzystać. –

+0

Hmmm, właśnie zauważyłem, że w przypadku tego rozwiązania nadal potrzebujesz osobnej fabuły dla każdej zmiennej. Być może można to osiągnąć za pomocą pętli.Jakieś pomysły, jeśli krata lub baza mogłaby osiągnąć to, czego chcę, bez pętli? – donodarazao

+0

Wygląda na to, że jest nieaktualny –