2012-07-16 11 views
10

Chciałbym wykreślić kilka różnych elementów danych za pomocą ggplot2, używając dwóch różnych skal kolorów (jeden ciągły i jeden dyskretny z dwóch różnych df). Mogę spiskować albo dokładnie, jak bym chciał, ale nie mogę ich zmusić do współpracy. Wygląda na to, że nie możesz mieć dwóch różnych skali kolorów działających na tej samej działce? Widziałem podobne pytania: here i here, a to doprowadziło mnie do przekonania, że ​​to, co chciałbym osiągnąć, jest po prostu niemożliwe w ggplot2, ale na wszelki wypadek, jeśli się mylę, chciałbym zilustrować mój problem, aby sprawdzić, czy istnieje obejść.Wykreślanie dyskretnych i ciągłych skal w tym samym ggplot

Mam kilka GIS danych strumieniowych, który ma jakieś kategoryczne atrybuty z nim związane, które mogę terenu (p1 w kodzie poniżej), aby uzyskać: enter image description here

Mam również zestaw miejscach, które mają ciągłą odpowiedź , które mogę również wykreślić (p2 w kodzie poniżej), aby uzyskać: enter image description here Jednak nie mogę połączyć dwóch (p3 w kodzie poniżej). I ten błąd

Error in scales[[prev_aes]] : attempt to select less than one element

zakomentowanie linię scale_colour_hue("Strahler order") + zmienia błąd do

Error: Discrete value supplied to continuous scale

Zasadniczo wydaje się, że ggplot2 wykorzystuje ten sam typ skalę (ciągły lub dyskretny) dla wywołania geom_path i połączeń geom_point . Więc kiedy przekazuję zmienną dyskretną, factor(Strahler), do skali scale_colour_gradientn, wykres nie powiedzie się.

Czy istnieje sposób obejścia tego? Byłoby zdumiewające, gdyby wystąpił argument o funkcji skalowania, informujący go, gdzie powinien być odwzorowany lub ustawiający atrybuty. Czy to możliwe?

Dziękujemy i kod powtarzalne poniżej:

library(ggplot2) 

### Download df's ### 
oldwd <- getwd(); tmp <- tempdir(); setwd(tmp) 
url <- "http://dl.dropbox.com/u/44829974/Data.zip" 
f <- paste(tmp,"\\tmp.zip",sep="") 
download.file(url,f) 
unzip(f) 


### Read in data ### 
riv_df <- read.table("riv_df.csv", sep=",",h=T) 
afr_df <- read.table("afr_df.csv", sep=",",h=T) 
vil_df <- read.table("vil_df.csv", sep=",",h=T) 


### Min and max for plot area ### 
xmin <- -18; xmax <- 3; ymin <- 4; ymax <- 15 


### Plot river data ### 
p1 <- ggplot(riv_df, aes(long, lat)) + 
    geom_map(mapping = aes(long , lat , map_id = id) , fill = "white" , data = afr_df , map = afr_df) + 
    geom_path(colour = "grey95" , mapping = aes(long , lat , group = group , size = 1) , data = afr_df) + 
    geom_path(aes(group = id , alpha = I(Strahler/6) , colour = factor(Strahler) , size = Strahler/6)) + 
    scale_alpha(guide = "none") + 
    scale_colour_hue("Strahler order") + 
    scale_x_continuous(limits = c(xmin , xmax) , expand = c(0 , 0)) + 
    scale_y_continuous(limits = c(ymin , ymax) , expand = c(0 , 0)) + 
    coord_map() 
print(p1) # This may take a little while depending on computer speed... 



### Plot response data ### 
p2 <- ggplot(NULL) + 
    geom_point(aes(X , Y , colour = Z) , size = 2 , shape = 19 , data = vil_df) + 
    scale_colour_gradientn(colours = rev(heat.colors(25)) , guide="colourbar") + 
    coord_equal() 
print(p2) 



### Plot both together ### 
p3 <- ggplot(riv_df, aes(long, lat)) + 
    geom_map(mapping = aes(long , lat , map_id = id) , fill = "white" , data = afr_df , map = afr_df) + 
    geom_path(colour = "grey95" , mapping = aes(long , lat , group = group , size = 1) , data = afr_df) + 
    geom_path(aes(group = id , alpha = I(Strahler/6) , colour = factor(Strahler) , size = Strahler/6)) + 
    scale_colour_hue("Strahler order") + 
    scale_alpha(guide = "none") + 
    scale_x_continuous(limits = c(xmin , xmax) , expand = c(0 , 0)) + 
    scale_y_continuous(limits = c(ymin , ymax) , expand = c(0 , 0)) + 
    geom_point(aes(X , Y , colour = Z) , size = 2 , shape = 19 , data = vil_df) + 
    scale_colour_gradientn(colours = rev(heat.colors(25)) , guide="colourbar") + 
    coord_map() 
print(p3) 
#Error in scales[[prev_aes]] : attempt to select less than one element 

### Clear-up downloaded files ### 
unlink(tmp,recursive=T) 
setwd(oldwd) 

Cheers,

Simon

+1

problem nie jest tak skomplikowane, jak mogłoby się wydawać. Zasadniczo można mapować tylko estetykę raz. Zatem wywołanie 'scale_colour_ *' dwa razy nie ma sensu dla ** ggplot2 **. Będzie próbował wtłoczyć jednego w drugie. – joran

+0

@joran Więc obecnie nie ma sposobu, aby odwzorować estetykę jednego koloru z ramki danych na ciągłą skalę i inną estetykę koloru z innej ramki danych na dyskretną skalę? Byłoby przydatny, czyż nie, gdyby można było podać dane do skali? –

+1

Nie można mieć wielu skal kolorów na tym samym wykresie, niezależnie od tego, czy jedno z nich jest ciągłe czy dyskretne. Autor pakietu powiedział, że nie ma zamiaru dodawać tego. Jest to dość skomplikowane w implementacji i sprawiłoby, że zbyt łatwe byłoby tworzenie niezwykle mylących wykresów. (Wiele osi Y nigdy nie zostanie zaimplementowanych z podobnych powodów.) – joran

Odpowiedz

9

Możesz to zrobić. Musisz grafikę siatki umieścić na jednym wykresie na drugim. Musisz mieć, aby uzyskać marginesy i odstępy itp., dokładnie w prawo, a ty musisz pomyśleć o przezroczystości górnych warstw. W skrócie ... to nie jest tego warte. Jak również może wprowadzać zamieszanie w fabułę.

Uważam jednak, że niektórzy ludzie mogą wskazać, jak to osiągnąć. N.B.Kiedyś code from this gist aby elementy w górnej działki przezroczyste więc nie nieprzezroczystych elementów poniżej:

grid.newpage() 
pushViewport(viewport(layout = grid.layout(1 , 1 , widths = unit(1 , "npc")))) 
print(p1 + theme(legend.position="none") , vp = viewport(layout.pos.row = 1 , layout.pos.col = 1)) 
print(p2 + theme(legend.position="none") , vp = viewport(layout.pos.row = 1 , layout.pos.col = 1)) 

Zobacz moją odpowiedź here do legendy, jak dodać do innego miejsca na układzie siatki.

enter image description here

5

Problemem nie jest tak skomplikowane, jak mogłoby się wydawać. Zasadniczo można mapować tylko estetykę raz. Dlatego dwukrotne wywołanie scale_colour_* nie ma sensu dla ggplot2. Będzie próbował wtłoczyć jednego w drugie.

Nie można mieć wielu skal kolorów na tym samym wykresie, niezależnie od tego, czy jedno z nich jest ciągłe czy dyskretne. Autor pakietu powiedział, że nie ma zamiaru dodawać tego. Jest to dość skomplikowane w implementacji i sprawiłoby, że zbyt łatwe byłoby tworzenie niezwykle mylących wykresów. (Wiele osi y nigdy nie zostanie zaimplementowanych z podobnych powodów.)

1

nie mam czasu w tej chwili, aby zapewnić pełną przykład działa, ale nie ma innego sposobu na to, że zasługuje na wspomniane tutaj: Fill and border colour in geom_point (scale_colour_manual) in ggplot

Zasadniczo, stosując geom_point w w połączeniu z shape = 21, color = NA pozwala kontrolować kolor serii punktów za pomocą estetyki fill, a nie color. Oto, jak wyglądał mój kod. Rozumiem, że nie ma żadnych danych przewidziane, ale mam nadzieję, że zapewnia ona z punktu wyjścia:

biloxi + 
    geom_point(data = filter(train, primary != 'na'), 
      aes(y = GEO_LATITUDE, x = GEO_LONGITUDE, fill = primary), 
      shape = 21, color = NA, size = 1) + 
    scale_fill_manual(values = c('dodgerblue', 'firebrick')) + 
    geom_point(data = test_map_frame, 
      aes(y = GEO_LATITUDE, x = GEO_LONGITUDE, color = var_score), 
      alpha = 1, size = 1) + 
    scale_color_gradient2(low = 'dodgerblue4', high = 'firebrick4', mid = 'white', 
        midpoint = mean(test_map_frame$var_score)) 

Zauważ, jak każde wywołanie geom_point wywołuje inną estetykę (color lub fill)

Powiązane problemy