Jarak dalam ruang dan waktu

10

Saya memiliki beberapa data titik yang mewakili lokasi lat-harian binatang, dengan cap waktu yang terkait.

Saya ingin mengidentifikasi semua poin di mana STATIONARY = TRUE. Suatu titik memenuhi syarat sebagai stasioner jika 100 km penyangga di sekitarnya tumpang tindih dengan tambahan (katakanlah) 5 titik yang berdekatan sementara . Jadi, jika hari ke 10 adalah tempat tujuan saya, saya ingin bertanya apakah 5 hari yang berdekatan untuk sementara berada dalam jarak 100 km dari titik ini. Jika hari 5,6,7,8 & 9; ATAU hari 11,12,13,14 & 15; ATAU hari-hari 8,9,11,12,13 (dll.) Berada di dalam buffer, kemudian STATIONARY = TRUE. Namun, jika hari 5,7,9,11 & 13 berada dalam buffer, tetapi bukan hari-hari alternatif (datar) di antara keduanya, maka STATIONARY = FALSE

Saya pikir beberapa jenis buffer jendela bergerak akan memberikan solusi, tetapi saya tidak tahu bagaimana cara mengimplementasikannya.

Saya telah mencoba untuk mengatasi masalah ini di ArcGIS dan R, tetapi sejauh ini tidak ada gelombang otak. Ini adalah yang paling dekat dengan solusi, tetapi tidak cocok, saya tidak berpikir: Identifikasi poin berurutan dalam buffer yang ditentukan

Berikut adalah beberapa data dummy, yang mendekati struktur data saya (meskipun dalam kenyataannya saya memiliki lokasi dua kali sehari (tengah hari dan tengah malam) dengan beberapa lokasi hilang - tetapi saya akan mengkhawatirkannya nanti)

x<-seq(0,15,length.out=20)
y<-seq(10,-10,length.out=20)
t<-seq(as.POSIXct('2013-07-01'), length.out = 20, by = "days")
data<-data.frame(cbind(x,y,t=as.data.frame.POSIXct(t)))


            x           y          t
1   0.0000000  10.0000000 2013-07-01
2   0.7894737   8.9473684 2013-07-02
3   1.5789474   7.8947368 2013-07-03
4   2.3684211   6.8421053 2013-07-04
5   3.1578947   5.7894737 2013-07-05
6   3.9473684   4.7368421 2013-07-06
7   4.7368421   3.6842105 2013-07-07
... ...         ...       ...
Tom Finch
sumber
1
Pertanyaan? Dengan asumsi semua 10 poin berada dalam buffer dan Anda memiliki pemisahan tanggal (mulai dari hari 1) dari 1-3-4-12-13-20-21-22-29-30-30 maka Anda mengatakan bahwa Anda hanya tertarik untuk memilih poin yang ada di hari 1,2,3,4 & 12?
Hornbydd
Tidak, saya hanya tertarik pada hari 1-4. Jika hewan 'meninggalkan' buffer kemudian kembali pada hari 12 (atau hari 6), maka itu akan 'membatalkan' periode diam - yaitu hewan harus berada di buffer pada hari 1-2-3-4-5 untuk titik di tengah buffer yang akan dihitung. Masuk akal? Saya sendiri tidak yakin ..
Tom Finch
1
Hanya untuk memeriksa, jika tempat tujuan adalah hari 7 maka Anda akan tertarik poin yang jatuh dalam 100km untuk hari 7,8,9,10 & 11?
Hornbydd
Titik 7 akan dipilih sebagai titik stasioner jika hari 8,9,10, 11 & 12 berada dalam jarak 100 km. Atau hari 5,6,8,9,10. Jadi, satu titik akan dipilih jika 5 titik sementara yang berdekatan lainnya (5 hari sebelumnya, 5 hari berikutnya, atau beberapa hari di kedua sisi) semuanya ada dalam buffer. Saya pikir jendela yang bergerak adalah cara terbaik untuk membuat konsep itu. Untuk setiap titik 'fokus', poin apa pun yang lebih dari 5 hari ke masa lalu / masa depan dapat dilupakan. Saya dapat memperbarui pertanyaan awal saya, karena saya sekarang memahaminya sedikit lebih ...
Tom Finch
Apa format datanya? Misalnya, apakah Anda memiliki setiap waktu / lokasi sebagai titik vektor dalam shapefile dan tabel atribut yang menyimpan waktu? Atau apakah setiap waktu / lokasi disimpan secara terpisah dalam berbagai bentuk yang berbeda? Apakah data bahkan tidak dalam format geospasial dan hanya dalam file Excel? Mengetahui hal ini akan membantu kami menjawab.

Jawaban:

12

Mari kita bagi menjadi beberapa bagian sederhana. Dengan melakukan itu, semua pekerjaan diselesaikan hanya dalam setengah lusin baris kode yang mudah diuji.

Pertama, Anda harus menghitung jarak. Karena data berada dalam koordinat geografis, berikut adalah fungsi untuk menghitung jarak pada datum bola (menggunakan rumus Haversine):

#
# Spherical distance.
# `x` and `y` are (long, lat) pairs *in radians*.
dist <- function(x, y, R=1) {
  d <- y - x
  a <- sin(d[2]/2)^2 + cos(x[2])*cos(y[2])*sin(d[1]/2)^2
  return (R * 2*atan2(sqrt(a), sqrt(1-a)))
}

Ganti ini dengan implementasi favorit Anda jika Anda mau (seperti yang menggunakan datum ellipsoidal).

Selanjutnya, kita perlu menghitung jarak antara setiap "titik dasar" (diperiksa untuk staionaritas) dan lingkungan temporal. Itu hanya masalah melamar distke lingkungan:

#
# Compute the distances between an array of locations and a base location `x`.
dist.array <- function(a, x, ...) apply(a, 1, function(y) dist(x, y, ...))

Ketiga - ini adalah ide kunci - titik-titik stasioner ditemukan dengan mendeteksi lingkungan dari 11 titik yang memiliki setidaknya lima berturut-turut yang jaraknya cukup kecil. Mari kita terapkan ini sedikit lebih umum dengan menentukan panjang nilai true nilai terlama dalam array logis nilai boolean:

#
# Return the length of the longest sequence of true values in `x`.
max.subsequence <- function(x) max(diff(c(0, which(!x), length(x)+1)))

(Kami menemukan lokasi dari nilai - nilai salah , secara berurutan, dan menghitung perbedaannya: ini adalah panjang dari nilai-nilai non-palsu selanjutnya. Panjang terbesar akan dikembalikan.)

Keempat, kami menerapkan max.subsequenceuntuk mendeteksi titik stasioner.

#
# Determine whether a point `x` is "stationary" relative to a sequence of its
# neighbors `a`.  It is provided there is a sequence of at least `k`
# points in `a` within distance `radius` of `x`, where the earth's radius is
# set to `R`.
is.stationary <- function(x, a, k=floor(length(a)/2), radius=100, R=6378.137) 
  max.subsequence(dist.array(a, x, R) <= radius) >= k

Itu semua adalah alat yang kita butuhkan.


Sebagai contoh, mari kita buat beberapa data menarik yang memiliki beberapa rumpun titik stasioner. Saya akan mengambil jalan acak di dekat Khatulistiwa.

set.seed(17)
n <- 67
theta <- 0:(n-1) / 50 - 1 + rnorm(n, sd=1/2)
rho <- rgamma(n, 2, scale=1/2) * (1 + cos(1:n / n * 6 * pi))
lon <- cumsum(cos(theta) * rho); lat <- cumsum(sin(theta) * rho)

Array londan latberisi koordinat, dalam derajat, ntitik secara berurutan. Menerapkan alat kami sangat mudah setelah pertama kali mengubahnya menjadi radian:

p <- cbind(lon, lat) * pi / 180 # Convert from degrees to radians
p.stationary <- sapply(1:n, function(i) 
  is.stationary(p[i,], p[max(1,i-5):min(n,i+5), ], k=5))

Argumen p[max(1,i-5):min(n,i+5), ]mengatakan untuk melihat sejauh 5 langkah waktu atau sejauh 5 langkah dari titik dasar p[i,]. Termasuk k=5mengatakan untuk mencari urutan 5 atau lebih dalam satu baris yang berada dalam 100 km dari titik dasar. (Nilai 100 km ditetapkan sebagai default is.stationarytetapi Anda dapat menimpanya di sini.)

Outputnya p.stationaryadalah vektor logis yang menunjukkan stasioneritas: kita memiliki apa yang kita inginkan. Namun, untuk memeriksa prosedur, lebih baik memplot data dan hasil ini daripada memeriksa array nilai. Di plot berikut ini saya menunjukkan rute dan titik-titiknya. Setiap titik kesepuluh diberi label sehingga Anda dapat memperkirakan berapa banyak yang mungkin tumpang tindih dalam rumpun stasioner. Titik stasioner digambar ulang dengan warna merah solid untuk menyorotnya dan dikelilingi oleh buffer 100 km.

Angka

plot(p, type="l", asp=1, col="Gray", 
     xlab="Longitude (radians)", ylab="Latitude (radians)")
points(p)
points(p[p.stationary, ], pch=19, col="Red", cex=0.75)
i <- seq(1, n, by=10)
#
# Because we're near the Equator in this example, buffers will be nearly 
# circular: approximate them.
disk <- function(x, r, n=32) {
  theta <- 1:n / n * 2 * pi
  return (t(rbind(cos(theta), sin(theta))*r + x))
}
r <- 100 / 6378.137  # Buffer radius in radians
apply(p[p.stationary, ], 1, function(x) 
  invisible(polygon(disk(x, r), col="#ff000008", border="#00000040")))
text(p[i,], labels=paste(i), pos=3, offset=1.25, col="Gray")

Untuk pendekatan (berbasis statistik) lainnya untuk menemukan titik diam dalam data yang dilacak, termasuk kode kerja, silakan kunjungi /mathematica/2711/clustering-of-space-time-data .

whuber
sumber
Wow terima kasih! berharap untuk mendapatkan kepalaku di sekitar ini. terima kasih sekali lagi atas waktu dan usaha Anda
Tom Finch