Unisci i dati dei punti spaziali ai poligoni in R


21

Sto cercando di eseguire un'unione spaziale tra dati puntuali e dati poligonali.

Ho dati che indicano le coordinate spaziali di un evento nel mio file CSV A e ho un altro file, shapefile B, che contiene i confini di un'area come poligoni.

head(A)
  month   longitude latitude lsoa_code                   crime_type
1 2014-09 -1.550626 53.59740 E01007359        Anti-social behaviour
2 2014-09 -1.550626 53.59740 E01007359                 Public order
3 2014-09 -1.865236 53.93678 E01010646        Anti-social behaviour

head(B@data)
  code      name                                  altname
0 E05004934 Longfield, New Barn and Southfleet    <NA>
1 E05000448                   Lewisham Central    <NA>
2 E05003149                            Hawcoat    <NA>

Voglio unire i dati del crimine A al mio shapefile B per mappare gli eventi criminali che si verificano nella mia area A. Sfortunatamente non posso eseguire un join di attributi basato sul fatto codeche il codice in A si riferisce a unità diverse rispetto al codice in B.

Ho letto una serie di tutorial e post ma non sono riuscito a trovare una risposta. Provai:

joined = over(A, B)

e overlay, ma non ho realizzato quello che volevo.

C'è un modo per fare questo join direttamente o sarebbe necessaria una trasformazione intermedia da A a un altro formato?

Concettualmente, voglio selezionare quei punti di A che rientrano nelle codearee di B (simile a "join basato sulla posizione spaziale in ArcGIS").

Qualcuno ha questo problema e risolto?


Hai guardato point.in.polygon()nel pacchetto sp?

@ arvi1000 Ho e proverò di nuovo. Il mio pensiero point.in.polygonera se questo avrebbe preservato le variabili monthe crime_type. Lo sai?
— ben_aaron,

Ho provato un po 'di più con point.in.polye ho finalmente selezionato quei punti che rientrano nei poligoni pertinenti. Grazie.
— ben_aaron,

Quindi forse dovresti rispondere alla tua stessa domanda con la tua soluzione. Ricorda, le buone risposte sono le caratteristiche di questo sito.
— SlowLearner

Risposte:


8

La funzione point.in.poly nel pacchetto spatialEco restituisce un oggetto SpatialPointsDataFrame dei punti che intersecano un oggetto poligono sp e facoltativamente aggiunge gli attributi poligono.

Innanzitutto, aggiungere i pacchetti richiesti e creare alcuni dati di esempio.

require(spatialEco)
require(sp)
data(meuse)
coordinates(meuse) = ~x+y
sr1=Polygons(list(Polygon(cbind(c(180114, 180553, 181127, 181477, 181294, 181007, 180409,
  180162, 180114), c(332349, 332057, 332342, 333250, 333558, 333676,
  332618, 332413, 332349)))),'1')
sr2=Polygons(list(Polygon(cbind(c(180042, 180545, 180553, 180314, 179955, 179142, 179437,
  179524, 179979, 180042), c(332373, 332026, 331426, 330889, 330683,
  331133, 331623, 332152, 332357, 332373)))),'2')
sr3=Polygons(list(Polygon(cbind(c(179110, 179907, 180433, 180712, 180752, 180329, 179875,
  179668, 179572, 179269, 178879, 178600, 178544, 179046, 179110),
  c(331086, 330620, 330494, 330265, 330075, 330233, 330336, 330004,
  329783, 329665, 329720, 329933, 330478, 331062, 331086)))),'3')
sr4=Polygons(list(Polygon(cbind(c(180304, 180403,179632,179420,180304),
  c(332791, 333204, 333635, 333058, 332791)))),'4')
sr=SpatialPolygons(list(sr1,sr2,sr3,sr4))
srdf=SpatialPolygonsDataFrame(sr, data.frame(row.names=c('1','2','3','4'), PIDS=1:4, y=runif(4)))

Ora, diamo una rapida occhiata ai dati e li tracciamo.

head(srdf@data)  # polygons
head(meuse@data) # points
plot(srdf)
points(meuse, pch=20)

Infine, possiamo intersecare i punti con i poligoni. I risultati saranno un oggetto SpatialPointsDataFrame con, in questo caso, due attributi extra (PIDS, y) contenuti nei dati del poligono srdf.

  pts.poly <- point.in.poly(meuse, srdf)
    head(pts.poly@data)

Se non esiste una colonna di identificazione univoca nei dati del poligono, è possibile aggiungerne facilmente una.

srdf@data$poly.ids <- 1:nrow(srdf) 

Una volta incrociati i punti e i poligoni, possiamo aggregare i punti usando gli ID poligonali univoci che erano un attributo nei dati del poligono.

# Number of points in each polygon
tapply(pts.poly@data$lead, pts.poly@data$PIDS, FUN=length)

# Mean lead in each polygon
tapply(pts.poly@data$lead, pts.poly@data$PIDS, FUN=mean)

@ arvi1000, sì ma sp :: point.in.polygon produce un valore logico. SpatialEco: point.in.poly è un wrapper per over ma restituisce sp SpialialPointsDataFrame e scorciatoie in alcuni passaggi relativi agli attributi poligonali, proprio come raster: intersect fa per rgeos :: gIntersect.
— Jeffrey Evans,

sp::point.in.polygonrestituisce effettivamente un valore numerico (0 = punto esterno, 1 = interno, 2 = sul bordo, 3 = sul vertice). Potrebbe essere la cosa giusta per alcune circostanze. Ho pensato che fosse utile annotare qui, dato che questo è un risultato top di Google per i termini correlati
— arvi1000

27

over()dal pacchetto sppuò essere un po 'confuso ma funziona bene. Suppongo che tu abbia già reso "A" spaziale con coordinates(A) <- ~longitude+latitude:

# Overlay points and extract just the code column: 
a.data <- over(A, B[,"code"])

Invece di un oggetto spaziale punto, questo ti dà semplicemente un frame di dati, con lo stesso no. righe come A e una singola variabile "codice" da ciascun poligono che si intersecano da B.

# Add that data back to A:
A$bcode <- a.data$code

Ho scoperto over()di avere problemi con i punti ai vertici dei poligoni, anche se penso che questa sia la soluzione più semplice che ho trovato finora.
— JMT2080AD,

Che problemi hai avuto?
— Simbamangu,

Esclusione. Ho bisogno di esplorarlo ulteriormente. Ti fornirò alcuni dati più tardi oggi e possiamo esaminarli insieme se sei interessato. Potrei sbagliarmi, ma sono abbastanza sicuro che ci siano alcune degenerazioni nell'algoritmo che devono essere prese in considerazione, almeno per i miei dati.
— JMT2080AD,

Non importa. Deve essere qualcosa con i miei dati. Questo set sperimentale funziona benissimo. r-fiddle.org/#/fiddle?id=m5sTjE4N&version=1
— JMT2080AD

1
Questo è un approccio molto più semplice rispetto alla risposta accettata e non richiede l'installazione di pacchetti aggiuntivi diversi da rgdal.
— Bryce Frank,

0

Ecco una soluzione simile a dplyr:

library(spdplyr)

ukcounties <- geojsonio::geojson_read("data/Westminster_Parliamentary_Constituencies_December_2018_UK_BGC/uk_country.geojson",
                                      what = "sp")
pop <- read_excel("data/SAPE20DT7-mid-2017-parlicon-syoa-estimates-unformatted.xls",sheet = "data")
pop <- janitor::clean_names(pop)

ukcounties_pop <- ukcounties %>% inner_join(pop, by = c("pcon18nm" = "pcon11nm"))

I dati sulla popolazione provengono da: https://www.ons.gov.uk/peoplepopulationandcommunity/populationandmigration/populationestimates/datasets/par Parliamentaryconstituencymidyearpopulationestimates

Ho dovuto convertire i file di forma scaricati da in geoJson: https://geoportal.statistics.gov.uk/datasets/westminster-parparlary-constituencies-december-2018-uk-bgc/data?page=1

Puoi farlo tramite:

uk_constituencies <- readOGR("data/Westminster_Parliamentary_Constituencies_December_2018_UK_BGC/Westminster_Parliamentary_Constituencies_December_2018_UK_BGC.shp")
uk_constituencies # this is in tmerc format. we need to convert it to WGS84 required by geoJson format.

# First Convert to Longitude / Latitude with WGS84 Coordinate System
wgs84 = '+proj=longlat +datum=WGS84'
uk_constituencies_trans <- spTransform(uk_constituencies, CRS(wgs84))

# Convert from Spatial Dataframe to GeoJSON
uk_constituencies_json <- geojson_json(uk_constituencies_trans)

# Save as GeoJSON file on the file system.
geojson_write(uk_constituencies_json, file = "data/Westminster_Parliamentary_Constituencies_December_2018_UK_BGC/uk_country.geojson")

#read back in:
ukcounties <- geojsonio::geojson_read("data/Westminster_Parliamentary_Constituencies_December_2018_UK_BGC/uk_country.geojson",
                                      what = "sp")
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.