Dari sp::over
bantuan:
x = "SpatialPoints", y = "SpatialPolygons" returns a numeric
vector of length equal to the number of points; the number is
the index (number) of the polygon of ‘y’ in which a point
falls; NA denotes the point does not fall in a polygon; if a
point falls in multiple polygons, the last polygon is
recorded.
Jadi, jika Anda mengonversi SpatialPolygonsDataFrame
ke SpatialPolygons
Anda mendapatkan kembali vektor indeks dan Anda dapat mengelompokkan poin Anda pada NA
:
> over(pts,as(ply,"SpatialPolygons"))
[1] NA 1 1 NA 1 1 NA NA 1 1 1 NA NA 1 1 1 1 1 NA NA NA 1 NA 1 NA
[26] 1 1 1 NA NA NA NA NA 1 1 NA NA NA 1 1 1 NA 1 1 1 NA NA NA 1 1
[51] 1 NA NA NA 1 NA 1 NA 1 NA NA 1 NA 1 1 NA 1 1 NA 1 NA 1 1 1 1
[76] 1 1 1 1 1 NA NA NA 1 NA 1 NA NA NA NA 1 1 NA 1 NA NA 1 1 1 NA
> nrow(pts)
[1] 100
> pts = pts[!is.na(over(pts,as(ply,"SpatialPolygons"))),]
> nrow(pts)
[1] 54
> head(pts@data)
var1 var2
2 0.04001092 v
3 0.58108350 v
5 0.85682609 q
6 0.13683264 y
9 0.13968804 m
10 0.97144627 o
>
Bagi yang ragu, inilah bukti bahwa overhead konversi bukan masalah:
Dua fungsi - metode pertama Jeffrey Evans, lalu yang asli, lalu konversi yang diretas, kemudian versi berdasarkan gIntersects
jawaban Josh O'Brien:
evans <- function(pts,ply){
prid <- over(pts,ply)
ptid <- na.omit(prid)
pt.poly <- pts[as.numeric(as.character(row.names(ptid))),]
return(pt.poly)
}
rowlings <- function(pts,ply){
return(pts[!is.na(over(pts,as(ply,"SpatialPolygons"))),])
}
rowlings2 <- function(pts,ply){
class(ply) <- "SpatialPolygons"
return(pts[!is.na(over(pts,ply)),])
}
obrien <- function(pts,ply){
pts[apply(gIntersects(columbus,pts,byid=TRUE),1,sum)==1,]
}
Sekarang untuk contoh dunia nyata, saya telah menyebarkan beberapa poin acak ke columbus
set data:
require(spdep)
example(columbus)
pts=data.frame(
x=runif(100,5,12),
y=runif(100,10,15),
z=sample(letters,100,TRUE))
coordinates(pts)=~x+y
Kelihatan bagus
plot(columbus)
points(pts)
Periksa fungsi melakukan hal yang sama:
> identical(evans(pts,columbus),rowlings(pts,columbus))
[1] TRUE
Dan jalankan 500 kali untuk pembandingan:
> system.time({for(i in 1:500){evans(pts,columbus)}})
user system elapsed
7.661 0.600 8.474
> system.time({for(i in 1:500){rowlings(pts,columbus)}})
user system elapsed
6.528 0.284 6.933
> system.time({for(i in 1:500){rowlings2(pts,columbus)}})
user system elapsed
5.952 0.600 7.222
> system.time({for(i in 1:500){obrien(pts,columbus)}})
user system elapsed
4.752 0.004 4.781
Sesuai intuisi saya, ini bukan overhead yang bagus, sebenarnya mungkin lebih sedikit overhead daripada mengubah semua indeks baris menjadi karakter dan kembali, atau menjalankan na.omit untuk mendapatkan nilai yang hilang. Yang kebetulan mengarah ke mode kegagalan evans
fungsi lainnya ...
Jika satu baris bingkai data poligon adalah semua NA
(yang benar-benar valid), maka hamparan dengan SpatialPolygonsDataFrame
untuk titik-titik dalam poligon tersebut akan menghasilkan bingkai data keluaran dengan semuaNA
s, yang evans()
kemudian akan turun:
> columbus@data[1,]=rep(NA,20)
> columbus@data[5,]=rep(NA,20)
> columbus@data[17,]=rep(NA,20)
> columbus@data[15,]=rep(NA,20)
> set.seed(123)
> pts=data.frame(x=runif(100,5,12),y=runif(100,10,15),z=sample(letters,100,TRUE))
> coordinates(pts)=~x+y
> identical(evans(pts,columbus),rowlings(pts,columbus))
[1] FALSE
> dim(evans(pts,columbus))
[1] 27 1
> dim(rowlings(pts,columbus))
[1] 28 1
>
TAPI gIntersects
lebih cepat, bahkan dengan harus menyapu matriks untuk memeriksa persimpangan di R daripada dalam kode C. Saya menduga ini adalah prepared geometry
keterampilan GEOS, membuat indeks spasial - ya, dengan prepared=FALSE
itu membutuhkan waktu sedikit lebih lama, sekitar 5,5 detik.
Saya terkejut tidak ada fungsi untuk langsung mengembalikan indeks atau poin. Ketika saya menulis splancs
20 tahun yang lalu fungsi point-in-polygon memiliki keduanya ...