Eu tenho um SpatialPointsDataFrame
com alguns dados adicionais. Gostaria de extrair esses pontos dentro de um polígono e, ao mesmo tempo, preservar o SPDF
objeto e seus dados correspondentes.
Até agora, tive pouca sorte e recorri à correspondência e à fusão por meio de um ID comum, mas isso só funciona porque eu agrupei os dados com o IDS individual.
Aqui está um exemplo rápido: estou procurando pontos dentro do quadrado vermelho.
library(sp)
set.seed(357)
pts <- data.frame(x = rnorm(100), y = rnorm(100), var1 = runif(100), var2 = sample(letters, 100, replace = TRUE))
coordinates(pts) <- ~ x + y
class(pts)
plot(pts)
axis(1); axis(2)
ply <- matrix(c(-1,-1, 1,-1, 1,1, -1,1, -1,-1), ncol = 2, byrow = TRUE)
ply <- SpatialPolygons(list(Polygons(list(Polygon(ply)), ID = 1)))
ply <- SpatialPolygonsDataFrame(Sr = ply, data = data.frame(polyvar = 357))
plot(ply, add = TRUE, border = "red")
A abordagem mais óbvia seria usar over
, mas isso retorna os dados do polígono.
> over(pts, ply)
polyvar
1 NA
2 357
3 357
4 NA
5 357
6 357
Respostas:
Da
sp::over
ajuda:Portanto, se você converter seu
SpatialPolygonsDataFrame
paraSpatialPolygons
você, receberá de volta um vetor de índices e poderá definir seus pontos emNA
:Para os que duvidam, aqui estão as evidências de que a sobrecarga da conversão não é um problema:
Duas funções - primeiro o método de Jeffrey Evans, depois meu original, depois minha conversão hackeada, depois uma versão baseada na
gIntersects
resposta de Josh O'Brien:Agora, para um exemplo do mundo real, eu espalhei alguns pontos aleatórios pelo
columbus
conjunto de dados:Parece bom
Verifique se as funções estão fazendo a mesma coisa:
E execute 500 vezes para fazer comparações:
De acordo com minha intuição, não é uma sobrecarga muito grande; na verdade, pode ser uma sobrecarga menor do que converter todos os índices de linha em caracteres e vice-versa ou executar na.omit para obter valores ausentes. Que, aliás, leva a outro modo de falha da
evans
função ...Se uma linha do quadro de dados de polígonos for toda
NA
(o que é perfeitamente válido), a sobreposiçãoSpatialPolygonsDataFrame
de pontos nesse polígono produzirá um quadro de dados de saída com todos osNA
s, queevans()
serão eliminados:MAS
gIntersects
é mais rápido, mesmo com a varredura da matriz para verificar as interseções no código R e não no código C. Suspeito que sejam asprepared geometry
habilidades do GEOS, criando índices espaciais - sim, comprepared=FALSE
isso demora um pouco mais, cerca de 5,5 segundos.Estou surpreso que não haja uma função para retornar diretamente os índices ou os pontos. Quando escrevi
splancs
há 20 anos, as funções point-in-polygon tinham ambas ...fonte
sp
fornece um formato mais curto para selecionar recursos com base na interseção espacial, seguindo o exemplo do OP:a partir de:
Nos bastidores, é a abreviação de
O que deve ser observado é que existe um
geometry
método que descarta atributos:over
altera o comportamento se o segundo argumento tiver atributos ou não (essa foi a confusão do OP). Isso funciona em todas as classes Spatial *sp
, embora algunsover
métodos exijamrgeos
, consulte esta vinheta para obter detalhes, por exemplo, o caso de várias correspondências para polígonos sobrepostos.fonte
Você estava no caminho certo com mais de. Os nomes de nomes de objeto do objeto retornado correspondem ao índice de linhas dos pontos. Você pode implementar sua abordagem exata com apenas algumas linhas de código adicionais.
fonte
É isso que você procura?
Uma observação, na edição: a chamada de empacotamento para
apply()
é necessária para fazer isso funcionar comSpatialPolygons
objetos arbitrários , possivelmente contendo mais de um recurso de polígono. Agradeço ao @Spacedman por me incentivar a demonstrar como aplicar isso ao caso mais geral.fonte
ply
tiver mais de um recurso, porquegIntersects
retorna uma matriz com uma linha para cada recurso. Você provavelmente pode varrer as linhas por um valor TRUE.apply(gIntersects(pts, ply, byid=TRUE), 2, any)
. De fato, vou adiante e mudarei a resposta para isso, já que também abrange o caso de um único polígono.any
. Isso pode ser marginalmente mais rápido que a versão que eu acabei de comparar.obrien
erowlings2
corre pescoço e pescoço, comobrien
talvez 2% mais rápido.pp
deve ter umID
que indica em qual polígono os pontos estão localizados.Aqui está uma abordagem possível usando o
rgeos
pacote. Basicamente, utiliza agIntersection
função que permite interceptar doissp
objetos. Ao extrair os IDs desses pontos que estão dentro do polígono, você poderá subconfigurar o originalSpatialPointsDataFrame
, mantendo todos os dados correspondentes. O código é quase auto-explicativo, mas se houver alguma dúvida, não hesite em perguntar!fonte
tmp
serpts.intersect
? Além disso, a análise dos dimnames retornados dessa maneira depende do comportamento não documentado.tmp
, esqueceu de removê-lo ao terminar o código. Além disso, você está certo em analisar o arquivodimnames
. Esta era uma espécie de uma solução rápida para fornecer a pergunta com uma resposta rápida, e há certamente são melhores (e mais universal) se aproxima, por exemplo, o seu :-)Existe uma solução extremamente simples usando a
spatialEco
biblioteca.Veja o resultado:
fonte