Creare un'istanza di poligono spaziale senza usare uno shapefile in R


22

Quindi, il solito modo in cui leggiamo uno shapefile in R è tramite il pacchetto maptools, in questo modo:

sfdata <- readShapeSpatial("/path/to/my/shapefile.shp", proj4string=CRS("+proj=longlat"))

Tuttavia, ho un caso d'uso in cui non ho uno shapefile.shp ma invece ho una serie di coordinate poligonali

16.484375 59.736328125,17.4951171875 55.1220703125,24.74609375 55.0341796875,22.5927734375 61.142578125,16.484375 59.736328125

e la sua proiezione corrispondente

coord. ref. : +proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0 

Come posso "istanziare" sfdata (che sarà un "oggetto poligonale") direttamente da questi dati? (senza andare in una rotonda per creare un file di forma con questi dati e quindi leggere dal file di forma appena creato)

Risposte:


35

Per prima cosa prendi le coordinate in una matrice a 2 colonne:

> xym
         [,1]     [,2]
[1,] 16.48438 59.73633
[2,] 17.49512 55.12207
[3,] 24.74609 55.03418
[4,] 22.59277 61.14258
[5,] 16.48438 59.73633

Quindi crea un poligono, avvolgilo in un oggetto Poligoni, quindi avvolgilo in un oggetto SpatialPolygons:

> library(sp)
> p = Polygon(xym)
> ps = Polygons(list(p),1)
> sps = SpatialPolygons(list(ps))

La ragione di questo livello di complessità è che un poligono è un semplice anello, un oggetto Poligoni può essere più anelli con un ID (qui impostato su 1) (quindi è come una singola funzione in un GIS) e uno SpatialPolygons può avere un CRS . Ooh, probabilmente dovrei impostarlo:

> proj4string(sps) = CRS("+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0")

Se vuoi trasformarlo in SpatialPolygonsDataFrame (che è ciò che viene fuori da readShapeSpatial quando lo shapefile è poligoni), allora fai:

> data = data.frame(f=99.9)
> spdf = SpatialPolygonsDataFrame(sps,data)
> spdf

dando questo:

> summary(spdf)
Object of class SpatialPolygonsDataFrame
Coordinates:
       min      max
x 16.48438 24.74609
y 55.03418 61.14258
Is projected: FALSE 
proj4string :
[+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0]
Data attributes:
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
   99.9    99.9    99.9    99.9    99.9    99.9 

+1 Esposizione molto bella e chiara. È bello vedere il codice spezzato dalle spiegazioni piuttosto che essere offerto come un blocco monolitico!
whuber

Eccellente ... fantastico vedere come questi oggetti sono messi insieme! Ho bisogno di vedere più pagine di aiuto R scritte chiaramente in questo modo.
Simbamangu,

È qualcosa che devo ri-insegnare a me stesso ogni volta che voglio farlo, quindi ne approfitto per insegnare ad altre persone!
Spacedman

1
eccellente ... come farei per aggiungere più poligoni ID (f) unici al frame di dati?
mga

2
Affinché questa risposta abbia una validità più generale, potresti mostrare come farlo in caso di più poligoni? Questo è un po 'complicato.
Tomas,

2

Per completare l'eccellente risposta di Spacedman nel caso in cui i tuoi dati contengano più poligoni, ecco un codice che utilizza dplyr:

library(dplyr)
library(ggplot2)
library(sp)
## use data from ggplot2:::geom_polygon example:
positions <- data.frame(id = rep(factor(c("1.1", "2.1", "1.2", "2.2", "1.3", "2.3")), 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)) %>% as.tbl


df_to_spp <- positions %>%
  group_by(id) %>%
  do(poly=select(., x, y) %>%Polygon()) %>%
  rowwise() %>%
  do(polys=Polygons(list(.$poly),.$id)) %>%
  {SpatialPolygons(.$polys)}

## plot it
plot(df_to_spp)

Solo per divertimento, puoi confrontare con la trama ottenuta ggplot2usando il frame di dati iniziale:

ggplot(positions) + 
  geom_polygon(aes(x=x, y=y, group=id), colour="black", fill=NA)

Si noti che il codice sopra presuppone che tu abbia un solo polognone per ID. Se alcuni ID avevano poligoni disgiunti, suppongo che si dovrebbe aggiungere un'altra colonna nel set di dati, prima group_byl'id secondario, quindi usare group_by(upper-id)invece dirowwise

Stesso codice usando la purrr::mapfunzione:

df_to_spp <- positions %>%
  nest(-id) %>%
  mutate(Poly=purrr::map(data, ~select(., x, y)  %>% Polygon()),
         polys=map2(Poly, id, ~Polygons(list(.x),.y))) %>%
  {SpatialPolygons(.$polys)}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.