Verificando se os pontos se enquadram no polígono

19

Zillow tem um conjunto de arquivos de forma para diferentes bairros das principais cidades dos EUA. Eu queria verificar se certos edifícios estavam presentes em determinados bairros usando R:

library(rgeos)
library(sp)
library(rgdal)

df <- data.frame(Latitude =c(47.591351, 47.62212,47.595152),
                 Longitude = c(-122.332271,-122.353985,-122.331639),
                 names = c("Safeco Field", "Key Arena", "Century Link"))
coordinates(df) <- ~ Latitude + Longitude

wa.map <- readOGR("ZillowNeighborhoods-WA.shp", layer="ZillowNeighborhoods-WA")

sodo <- wa.map[wa.map$CITY == "Seattle"  & wa.map$NAME == "Industrial District", ]

Consigo traçar sem problemas

plot(sodo)
points(df$Latitude ~ df$Longitude, col = "red", cex = 1)

insira a descrição da imagem aqui

proj4Combino a string do shapefile com meu data.frame

CRSobj <- CRS("+proj=longlat +datum=NAD83 +no_defs +ellps=GRS80 +towgs84=0,0,0 ")
df@proj4string <- CRSobj

over(df, sodo)

Isso me dá um monte de NAvalores. Eu tentei esta resposta

spp <- SpatialPoints(df)
spp@proj4string <- CRSobj
over(spp, sodo)

mas ainda obtém apenas NAvalores. Alguma idéia do que mais eu deveria tentar?

Stedy
fonte

Respostas:

20

O espacial data.framenão está formado corretamente. Isso pode funcionar:

library(rgeos)
library(sp)
library(rgdal)

wa.map <- readOGR("ZillowNeighborhoods-WA.shp", layer="ZillowNeighborhoods-WA")

sodo <- wa.map[wa.map$CITY == "Seattle"  & wa.map$NAME == "Industrial District", ]

# Don't use df as name, it is an R function
# Better to set longitudes as the first column and latitudes as the second
dat <- data.frame(Longitude = c(-122.332271,-122.353985,-122.331639),
                  Latitude =c(47.591351, 47.62212,47.595152),
                  names = c("Safeco Field", "Key Arena", "Century Link"))
# Assignment modified according
coordinates(dat) <- ~ Longitude + Latitude
# Set the projection of the SpatialPointsDataFrame using the projection of the shapefile
proj4string(dat) <- proj4string(sodo)

over(dat, sodo)
#  STATE COUNTY    CITY                NAME REGIONID
#1    WA   King Seattle Industrial District   271892
#2  <NA>   <NA>    <NA>                <NA>       NA
#3  <NA>   <NA>    <NA>                <NA>       NA

over(sodo, dat)
#           names
#122 Safeco Field

fonte
7

Acabei de fazer a mesma coisa. A resposta de Pascal quase cobre, mas você pode precisar de duas etapas extras, como abaixo.

#After you create your list of latlongs you must set the proj4string to longlat
proj4string(dat) <- CRS("+proj=longlat")

#Before you re-set the proj4string to the one from sodo you must actually convert #your coordinates to the new projection
dat <- spTransform(dat, proj4string(sodo))
John Curry
fonte
Não está claro para mim em quais casos essas etapas adicionais são necessárias. Para mim, a solução da resposta do usuário32309 foi boa o suficiente.
djhurio
3
Depende do formato dos seus dados. Se estiver na projeção A e você quiser apenas declarar que usa proj4string e deve ser bom. Mas se estiver na projeção B e você precisar fazer uma conversão para a projeção A, precisará usar o spTransform.
John Curry
2

Eu usei uma abordagem semelhante à resposta aceita neste post, mas nunca fiquei realmente satisfeito com isso, então procurei alternativas e encontrei o sf biblioteca .

E usando esta biblioteca, você pode escrever um código como este:

library(sf)
# Shapefile from ABS: 
# https://www.abs.gov.au/AUSSTATS/[email protected]/DetailsPage/1270.0.55.004July%202016?OpenDocument
map = read_sf("data/ABS/shapes/SUA_2016_AUST.shp")

pnts_sf <- st_as_sf(pnts, coords = c('y', 'x'), crs = st_crs(map))

pnts <- pnts_sf %>% mutate(
  intersection = as.integer(st_intersects(geometry, map))
  , area = if_else(is.na(intersection), '', map$SUA_NAME16[intersection])
) 

pnts

Resultado:

         geometry intersection area    
*     <POINT [°]>        <int> <chr>   
1 (138.62 -34.92)           79 Adelaide
2 (138.58 -34.93)           79 Adelaide
3 (138.52 -34.95)           79 Adelaide
4 (152.71 -27.63)           60 Brisbane
5 (153.01 -27.57)           60 Brisbane
6  (150.73 -33.9)           31 Sydney  
7 (150.99 -33.92)           31 Sydney 

Eu publiquei esse código em outro post que era uma pergunta semelhante, aqui: Identificar ponto contendo polígono com o pacote R sf

Michael Gordon
fonte