Joindre des données de points spatiaux à des polygones dans R


21

J'essaie d'effectuer une jointure spatiale entre les données de points et les données de polygones.

J'ai des données qui indiquent les coordonnées spatiales d'un événement dans mon fichier csv A et j'ai un autre fichier, le fichier de formes B, qui contient les limites d'une zone sous forme de polygones.

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>

Je souhaite joindre les données de criminalité A à mon fichier de formes B pour cartographier les événements de criminalité qui se produisent dans ma région A. Malheureusement, je ne peux pas effectuer de jointure d'attribut codecar le code en A fait référence à des unités différentes de celles du code en B.

J'ai lu un certain nombre de didacticiels et d'articles, mais je n'ai pas trouvé de réponse. J'ai essayé:

joined = over(A, B)

et overlay , mais n'a pas accompli ce que je voulais.

Existe-t-il un moyen de faire cette jointure directement ou une transformation intermédiaire de A vers un autre format serait-elle nécessaire?

Conceptuellement, je veux sélectionner les points de A qui tombent dans le code zones de B (similaires à «joindre en fonction de l'emplacement spatial dans ArcGIS»).

Quelqu'un a-t-il eu ce problème et l'a-t-il résolu?


Avez-vous regardé point.in.polygon()dans le paquet sp?

@ arvi1000 J'ai et réessayerai. Ma pensée point.in.polygonétait de savoir si cela préserverait les variables monthet crime_type. Connaissez-vous cela?
ben_aaron

J'ai essayé un peu plus avec point.in.polyet j'ai finalement sélectionné les points qui tombent dans les polygones pertinents. Merci.
ben_aaron

Alors peut-être devriez-vous répondre à votre propre question avec votre solution. N'oubliez pas que ce site est une bonne réponse.
SlowLearner

Réponses:


8

La fonction point.in.poly du package spatialEco renvoie un objet SpatialPointsDataFrame des points qui coupent un objet polygone sp et ajoute éventuellement les attributs de polygone.

Ajoutons d'abord les packages requis et créons des exemples de données.

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)))

Maintenant, jetons un coup d'œil aux données et traçons-les.

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

Enfin, nous pouvons intersecter les points avec les polygones. Le résultat sera un objet SpatialPointsDataFrame avec, dans ce cas, deux attributs supplémentaires (PIDS, y) qui étaient contenus dans les données du polygone srdf.

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

S'il n'y a pas de colonne d'identification unique dans les données du polygone, vous pouvez facilement en ajouter une.

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

Une fois que nous avons intersecté les points et les polygones, nous pouvons agréger les points en utilisant les ID de polygone uniques qui étaient un attribut dans les données de polygone.

# 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, oui mais sp :: point.in.polygon produit une logique. Le spatialEco: point.in.poly est un wrapper pour over mais retourne un sp SpatialPointsDataFrame et raccourcit certaines étapes pour relier les attributs de polygone, un peu comme raster: intersect le fait pour rgeos :: gIntersect.
Jeffrey Evans

sp::point.in.polygonrenvoie en fait une valeur numérique (0 = le point est à l'extérieur, 1 = à l'intérieur, 2 = sur le bord, 3 = sur le sommet). Cela pourrait être la bonne chose dans certaines circonstances. J'ai pensé qu'il était utile de le noter ici, car il s'agit d'un résultat Google supérieur pour les termes connexes
arvi1000

27

over()à partir du paquet sppeut être un peu déroutant mais fonctionne bien. Je suppose que vous avez déjà créé l'espace "A" avec coordinates(A) <- ~longitude+latitude:

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

Au lieu d'un objet géographique ponctuel, cela vous donne simplement un bloc de données, avec le même non. lignes comme A, et une seule variable "code" de chaque polygone qui se croisent de B.

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

J'ai trouvé over()qu'il y avait des problèmes avec les points aux sommets des polygones, bien que je pense que c'est la solution la plus simple que j'ai trouvée jusqu'à présent.
JMT2080AD

Quels problèmes avez-vous rencontrés?
Simbamangu

Exclusion. Je dois l'explorer davantage. Je vous enverrai quelques données plus tard dans la journée et nous pourrons les examiner ensemble si cela vous intéresse. Je me trompe peut-être, mais je suis presque sûr qu'il y a des dégénérescences dans l'algorithme qui doivent être prises en compte, au moins pour mes données.
JMT2080AD

Ça ne fait rien. Cela doit être quelque chose avec mes données. Cet ensemble expérimental fonctionne très bien. r-fiddle.org/#/fiddle?id=m5sTjE4N&version=1
JMT2080AD

1
Il s'agit d'une approche beaucoup plus simple que la réponse acceptée et ne nécessite pas l'installation de packages supplémentaires autres que rgdal.
Bryce Frank

0

Voici une solution similaire à 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"))

Les données démographiques proviennent de: https://www.ons.gov.uk/peoplepopulationandcommunity/populationandmigration/populationestimates/datasets/parliamentaryconstituencymidyearpopulationestimates

J'ai dû convertir les fichiers de forme téléchargés depuis en geoJson: https://geoportal.statistics.gov.uk/datasets/westminster-parliamentary-constituencies-december-2018-uk-bgc/data?page=1

Vous pouvez le faire en:

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")
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.