2017-05-23 65 views
8

Chciałbym narysować SpatialPolygons z biblioteki sp z otworami w ggplot2. Dzięki innym pytania na StackOverflow, wiem, że jest to dozwolone, natomiast do czynienia z ruchem wskazówek zegara napisany wielokątów:
http://stackoverflow.com/questions/12047643/geom-polygon-with-multiple-hole/12051278#12051278
Rzeczywiście, podczas przekształcania SpatialPolygons użyciu broom::tidy (zastępując ggplot2::fortify), otwory wielokąty są zapisywane w kierunku ruchu wskazówek zegara, aby wyciągnąć jak dziury.
W ggplot2 sposób w jaki rysowane są wielokąty z otworami, wymusza ich losowanie jednokrotnie za pomocą fill, a innym razem za pomocą colour, w przeciwnym razie mogą pojawić się linie przecinające wielokąty. W przypadku wielu subpolygonów, niektóre z dziurami, jest to trudniejsze, kolejność elementów punktów zdefiniowanych przez broom::tidy może nie pozwalać na wypełnianie wielokątów (patrz rysunek poniżej).
Czy ktoś z was ma rozwiązanie, aby pozbyć się tego problemu z wypełnianiem?Rysuj przestrzenne poligony z wieloma subpoliami i dziurami za pomocą ggplot2

Oto powtarzalne przykład:

library(sp) 
library(ggplot2) 

# Create two polygons: second would be a hole inside the first 
xy = cbind(
    x = c(13.4, 13.4, 13.6, 13.6, 13.4), 
    y = c(48.9, 49, 49, 48.9, 48.9) 
    ) 
hole.xy <- cbind(
    x = c(13.5, 13.5, 13.45, 13.45, 13.5), 
    y = c(48.98, 48.92, 48.92, 48.98, 48.98) 
) 

# Transform as SpatialPolygons with holes 
xy.sp <- SpatialPolygons(list(
    Polygons(list(Polygon(xy), 
       Polygon(hole.xy, hole = TRUE)), "1"), 
    Polygons(list(Polygon(xy + 0.2), 
       Polygon(xy + 0.35), 
       Polygon(hole.xy + 0.2, hole = TRUE)), "2") 
)) 

# Transform SpatialObject to be used by ggplot2 
xy.sp.l <- broom::tidy(xy.sp) 

ggplot(xy.sp.l) + 
    geom_polygon(aes(x = long, y = lat, group = id, fill = id)) 

ggplot fill problem with SpatialPolygons with holes

+0

Jedno rozwiązanie pociąga za sobą oddzielenie wielokątów w wywołaniu funkcji SpatialPolygons. na przykład Dwa wielokąty o id = 2 stają się 2a i 2b. Czy jest to możliwe, czy szukasz rozwiązania od xy.sp.l. –

Odpowiedz

9

To może być dobry moment, aby "przejść" do pakietu sf. Praca z sf obiektu jest w rzeczywistości o wiele łatwiej w ggplot, dzięki geometrii geom_sf:

library("sf") 
library("rgeos") 
sf_poly <- as(xy.sp, "sf") 
sf::st_crs(sf_poly) <- 4326 
sf_poly$id <- c(1,2) 
ggplot(sf_poly) + 
    geom_sf(aes(fill = as.factor(id))) 

enter image description here

+0

Tak, rzeczywiście. Twoja odpowiedź rozwiązuje problem w prosty sposób. Myślę, że to zachęci ludzi mających ten problem do migracji do sf ... osobiście czekałem w chwili, gdy 'sf' był wystarczająco stabilny z parametrami i nazwami funkcji. Jednak to podnosi mój drugi problem polegający na tym, że mogę rysować wyrysowane obszary wielokątów za pomocą funkcji sf. Będę musiał zmodyfikować moją funkcję, aby umożliwić to za pomocą sf, a następnie ulotki z sf. Ale to jest kolejne pytanie, po raz kolejny ... Dzięki. –

+0

Akceptuję tę odpowiedź, aby ludzie przenieśli się do 'sf'.Ale druga odpowiedź jest przyznawana, ponieważ jest to odpowiedź na moje pytanie. –

1

Dodawanie wierszy ukazuje źródło problemu. Niebieski "wielokąt" jest rysowany, dolny -> górny -> otwór.

enter image description here

Ten kod (co nie jest bardzo elegancki, przepraszam) sprawia, że ​​droga wrócić do punktu wyjścia pierwszego kawałka przed przystąpieniem do 3rd.

library(dplyr) 
    extra <- xy.sp.l %>% 
     filter(piece != 1) %>% 
     group_by(id, group) %>% 
     summarise(last_pt = max(order)) 


for (n in 1:nrow(extra)) { 
    id_ex <- as.character(extra[n,"id"]) 
    x <- subset(xy.sp.l, id == id_ex & piece == 1 & order == 1) 
    x$order <- as.numeric(extra[n,"last_pt"]) + 0.5 
    xy.sp.l <- rbind(xy.sp.l,x) 
} 

xy.sp.l <- xy.sp.l[order(xy.sp.l$id, xy.sp.l$order),] 

enter image description here

+0

Dziękuję za odpowiedź. Wracając do jednego punktu pierwszego wielokąta wydaje się, że rozwiązuje problem dla dowolnego nowego porządku podrzędnego lub wielokąta. Domyślam się, że ta sztuczka może być użyta dla dowolnych wielokątów biblioteki 'sp' do wykreślenia w' ggplot2'. –

+0

Wierzę, że tak by było, ponieważ pozwala uniknąć problemu dodatkowych wielokątów (takich jak trójkąt powyżej). –

+0

Nagram tę odpowiedź, ponieważ odpowiada bezpośrednio na moje pytanie. Jednak, aby zachęcić ludzi do przejścia na "sf", akceptuję pierwszą odpowiedź. –

1

Ten post jest dobre pytanie, a już otrzymał wielkie odpowiedzi. Wierzę również, że ludzie powinni nauczyć się pracować z obiektami sf, ponieważ jest to następna generacja typu danych przestrzennych w R. Ale chcę się podzielić, że w tym przypadku geom_spatial z pakietu ggspatial może być opcją do wykreślenia SpatialPolygons.

library(sp) 
library(ggplot2) 
library(ggspatial) 

ggplot() + 
    geom_spatial(xy.sp, aes(fill = id)) 
# Ignoring argument 'mapping' in geom_spatial.SpatialPolygons 
# Autodetect projection: assuming lat/lon (epsg 4326) 

enter image description here