Tengo un SpatialPointsDataFrame
con algunos datos adicionales. Me gustaría extraer esos puntos dentro de un polígono y, al mismo tiempo, preservar el SPDF
objeto y sus datos correspondientes.
Hasta ahora he tenido poca suerte y he recurrido a la coincidencia y la fusión a través de una ID común, pero esto solo funciona porque tengo datos cuadriculados con IDS individuales.
Aquí hay un ejemplo rápido, estoy buscando puntos dentro del cuadrado rojo.
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")
El enfoque más obvio sería usar over
, pero esto devuelve los datos del polígono.
> over(pts, ply)
polyvar
1 NA
2 357
3 357
4 NA
5 357
6 357
Respuestas:
De la
sp::over
ayuda:Entonces, si convierte su
SpatialPolygonsDataFrame
aSpatialPolygons
, obtiene un vector de índices y puede subconjugar sus puntos enNA
:Para los que dudan, aquí hay evidencia de que la sobrecarga de conversión no es un problema:
Dos funciones: primero el método de Jeffrey Evans, luego mi original, luego mi conversión pirateada, luego una versión basada en
gIntersects
la respuesta de Josh O'Brien:Ahora, para un ejemplo del mundo real, he dispersado algunos puntos aleatorios sobre el
columbus
conjunto de datos:Se ve bien
Verifique que las funciones estén haciendo lo mismo:
Y corra 500 veces para la evaluación comparativa:
Según mi intuición, no es una gran sobrecarga, de hecho, podría ser menos una sobrecarga que convertir todos los índices de fila en caracteres y viceversa, o ejecutar na.omit para obtener valores perdidos. Lo que incidentalmente conduce a otro modo de falla de la
evans
función ...Si una fila del marco de datos de polígonos es todo
NA
(lo cual es perfectamente válido), entonces la superposición conSpatialPolygonsDataFrame
puntos en ese polígono producirá un marco de datos de salida con todos losNA
s, queevans()
luego caerán:PERO
gIntersects
es más rápido, incluso teniendo que barrer la matriz para verificar las intersecciones en R en lugar de en el código C. Sospecho que son lasprepared geometry
habilidades de GEOS, la creación de índices espaciales, sí, conprepared=FALSE
esto lleva un poco más de tiempo, unos 5,5 segundos.Me sorprende que no haya una función para devolver directamente los índices o los puntos. Cuando escribí hace
splancs
20 años, las funciones de punto en el polígono tenían ambas ...fuente
sp
proporciona una forma más corta para seleccionar entidades basadas en la intersección espacial, siguiendo el ejemplo de OP:a partir de:
Detrás de escena esto es la abreviatura de
Lo que hay que tener en cuenta es que hay un
geometry
método que elimina atributos:over
cambia el comportamiento si su segundo argumento tiene atributos o no (esto fue la confusión de OP). Esto funciona en todas las clases de Spatial *sp
, aunque algunosover
métodos lo requierenrgeos
, vea esta viñeta para obtener detalles, por ejemplo, el caso de coincidencias múltiples para polígonos superpuestos.fuente
Estabas en el camino correcto con más. Los nombres de fila del objeto devuelto corresponden al índice de fila de los puntos. Puede implementar su enfoque exacto con solo unas pocas líneas de código adicionales.
fuente
¿Es esto lo que buscas?
Una nota, en edición: la llamada de ajuste a
apply()
es necesaria para que esto funcione conSpatialPolygons
objetos arbitrarios , que posiblemente contengan más de una función de polígono. Gracias a @Spacedman por animarme a demostrar cómo aplicar esto al caso más general.fuente
ply
tiene más de una característica, porquegIntersects
devuelve una matriz con una fila para cada característica. Probablemente pueda barrer las filas para obtener un valor VERDADERO.apply(gIntersects(pts, ply, byid=TRUE), 2, any)
. De hecho, seguiré adelante y cambiaré la respuesta a eso, ya que abarca el caso de un solo polígono también.any
. Eso podría ser marginalmente más rápido que la versión que acabo de comparar.obrien
yrowlings2
corre cuello y cuello, conobrien
quizás un 2% más rápido.pp
debe tener unID
que indique en qué polígono se encuentran los puntos.Aquí hay un posible enfoque usando el
rgeos
paquete. Básicamente, hace uso de lagIntersection
función que le permite intersecar dossp
objetos. Al extraer los ID de esos puntos que se encuentran dentro del polígono, puede subconjugar su originalSpatialPointsDataFrame
y conservar todos los datos correspondientes. El código casi se explica por sí mismo, pero si tiene alguna pregunta, ¡no dude en preguntar!fuente
tmp
serpts.intersect
? Además, analizar los dimombres devueltos de esa manera depende del comportamiento indocumentado.tmp
, olvidó eliminarlo al terminar el código. Además, tienes razón al analizar eldimnames
. Esta fue una especie de solución rápida para proporcionar al interlocutor una respuesta rápida, y seguramente hay enfoques mejores (y más universales), por ejemplo el suyo: -)Hay una solución extremadamente simple usando la
spatialEco
biblioteca.Comprueba el resultado:
fuente