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.