Identifikasi titik berurutan dalam buffer yang ditentukan

8

Saya memiliki file titik, relokasi hewan setiap jam, dan saya ingin dapat menempatkan buffer di sekitar setiap titik dan menghitung jumlah titik berikutnya yang berada dalam zona buffer. Saya mencari metode yang akan bekerja di sepanjang file titik, seperti jendela bergerak, yang hanya akan menghitung titik-titik berikutnya yang berada dalam zona penyangga.

Misalnya pada titik 10 saya menempatkan buffer 1500m dan saya ingin tahu apakah titik 11 berada di dalam buffer dan jika demikian maka apakah titik 12 berada di dalam buffer dan sebagainya. Saya tidak ingin tahu apakah titik 52 berada di dalam zona buffer kecuali semua poin sebelumnya berada di dalam buffer. Saya juga tidak ingin tahu apakah poin 9 atau 8 dll berada dalam buffer.

Saya telah menemukan dan mencoba kotak alat tambahan yang disebut "analisis titik jendela bergerak" yang berfungsi sebagai jendela bergerak pada file titik. Ini bekerja dengan baik, tetapi sangat lambat, dan mencakup semua titik yang ada di dalam zona penyangga bahkan jika mereka bukan titik yang berurutan. Saya tidak dapat menemukan cara untuk membuatnya terlihat pada poin berurutan.

Saya ingin metode yang akan menyediakan tabel output karena saya memiliki banyak titik data untuk dilihat dengan cara ini.

Saya menggunakan ArcGIS 10. Setiap bantuan yang dapat diberikan oleh siapa pun akan sangat dihargai.

James
sumber
Poin Anda kemungkinan berasal sebagai daftar (x, y, waktu) data. Apakah Anda akan terbuka untuk melakukan pra-pemrosesan data ini (di luar ArcGIS) untuk mendapatkan informasi yang diinginkan?
whuber
Jika itu membuatnya lebih mudah maka pasti. Saya juga memproses data menggunakan AdehabitatLT dalam R yang menghitung jarak dan bantalan dll. Saya memahami proses yang disarankan oleh Sylvester di bawah ini tetapi saya berjuang untuk tahu harus mulai dari mana karena saya tidak begitu yakin alat mana yang perlu saya gunakan.
James
Ah! Karena Anda sudah menggunakan R, mari kita jelajahi solusi berbasis R.
whuber
Ada fungsi jendela geser dalam AdehabitatLT "sliwinltr" tapi saya tidak tahu bagaimana menggunakannya dalam contoh ini. Saya bahkan tidak tahu apakah itu bisa digunakan dengan cara ini.
James

Jawaban:

8

Diberikan daftar lokasi titik (lebih disukai dalam koordinat yang diproyeksikan, sehingga jaraknya mudah dihitung), masalah ini dapat diselesaikan dengan lima operasi sederhana :

  1. Hitung jarak titik-titik.

  2. Untuk setiap titik i, i = 1, 2, ..., identifikasi indeks titik-titik tersebut pada jarak kurang dari radius buffer (seperti 1500).

  3. Batasi indeks tersebut menjadi i atau lebih besar.

  4. Pertahankan hanya grup indeks berurutan pertama yang tidak memiliki jeda.

  5. Keluarkan hitungan grup itu.

Dalam R, masing-masing sesuai dengan satu operasi. Untuk menerapkan urutan ini pada setiap titik, akan lebih mudah untuk merangkum sebagian besar pekerjaan dalam fungsi yang kita tentukan , dengan demikian:

#
# forward(j, xy, r) counts how many contiguous rows in array xy, starting at index j,
#                   are within (Euclidean) distance r of the jth row of xy.
#
forward <- function(j, xy, r) {
  # Steps 1 and 2: compute an array of indexes of points within distance r of point j.
  i <- which(apply(xy, 1, function(x){sum((x-xy[j,])^2) <= r^2}))
  # Step 3: select only the indexes at or after j.
  i <- i[i >= j]
  # Steps 4 and 5: retain only the first consecutive group and count it.
  length(which(i <= (1:length(i) + j)))
}

(Lihat di bawah untuk versi yang lebih efisien dari fungsi ini.)

Saya telah membuat fungsi ini cukup fleksibel untuk menerima berbagai daftar titik ( xy) dan jarak buffer ( r) sebagai parameter.

Biasanya, Anda akan membaca file lokasi titik (dan, jika perlu, urutkan berdasarkan waktu). Di sini, untuk menunjukkan ini dalam tindakan, kami hanya akan menghasilkan beberapa data sampel secara acak :

# Create sample data
n<-16                                     # Number of points
set.seed(17)                              # For reproducibility
xy <- matrix(rnorm(2*n) + 1:n, n, 2) * 300
#
# Display the track.
plot(xy, xlab="x", ylab="y")
lines(xy, col="Gray")

Angka

Jarak tipikal mereka adalah 300 * Sqrt (2) = sekitar 500. Kami melakukan perhitungan dengan menerapkan fungsi ini ke titik-titik dalam arrayxy (dan kemudian menempelkan hasilnya kembali ke xy, karena ini akan menjadi format yang nyaman untuk mengekspor ke GIS ):

radius <- 1500
z <- sapply(1:n, function(u){forward(u,xy,radius)})
result <- cbind(xy, z)                              # List of points, counts

Anda kemudian akan menganalisis resultarray lebih lanjut , baik dalam Ratau dengan menulisnya ke file dan mengimpornya ke perangkat lunak lain. Berikut adalah hasil untuk data sampel :

                        z
  [1,]   -4.502615  551.5413 4
  [2,]  576.108979  647.8110 3
  [3,]  830.103893 1087.7863 4
  [4,]  954.819620 1390.0754 3
...
 [15,] 4977.361529 4146.7291 2
 [16,] 4783.446283 4511.9500 1

(Ingatlah bahwa penghitungan mencakup titik di mana mereka didasarkan, sehingga setiap penghitungan harus 1 atau lebih besar.)


Jika Anda memiliki ribuan titik, metode ini terlalu tidak efisien : ini menghitung terlalu banyak jarak titik-ke-titik yang tidak perlu. Tetapi karena kami telah merangkum pekerjaan dalam forwardfungsi, inefisiensi mudah untuk diperbaiki. Ini adalah versi yang akan bekerja lebih baik ketika lebih dari beberapa ratus poin terlibat:

forward <- function(j, xy, r) {
   n <- dim(xy)[1]     # Limit the search to the number of points in xy
   r2 <- r^2           # Pre-compute the squared distance threshold
   z <- xy[j,]         # Pre-fetch the base point coordinates
   i <- j+1            # Initialize an index into xy (just past point j)

   # Advance i while point i remains within distance r of point j.
   while(i <= n && sum((xy[i,]-z)^2) <= r2) i <- i+1

   # Return the count (including point j).
   i-j
}

Untuk menguji ini, saya membuat poin acak seperti sebelumnya tetapi memvariasikan dua parameter: n(jumlah poin) dan standar deviasi mereka (hard-coded seperti 300 di atas). Deviasi standar menentukan jumlah rata-rata poin dalam setiap buffer ("rata-rata" pada tabel di bawah): semakin banyak, semakin lama algoritma ini diperlukan untuk berjalan. (Dengan algoritme yang lebih canggih, waktu tayang tidak akan terlalu tergantung pada berapa banyak poin di setiap buffer.)

 Time (sec)    n    SD  Average  Distances checked per minute
 1.30       10^3     3  291      13.4 million
 1.72       10^4    30   35.7    12.5
 2.50       10^5   300    3.79    9.1
16.4        10^6  3000    1.04    3.8
whuber
sumber
Ini sepertinya solusi yang sempurna. Namun kode tidak dijalankan dari "z <- sapply (1: n), function (u) {forward (u, xy, radius)})" seperti yang tertulis: "tak terduga ',' di" z <- sapply (1: n), "Jika saya menghapus koma maka dikatakan: Kesalahan: fungsi 'tak terduga' di" z <- sapply (1: n) berfungsi "Adakah gagasan mengapa ini bisa terjadi?
James
Maaf; ada kesalahan ketik di sana: Saya akan menghapus ")" yang asing. (Saya membuat penyederhanaan menit terakhir dari kode ini. Ini telah diuji lebih dari yang saya akui!)
whuber
1
Bagus sekali, sedang berjalan sekarang. Saya baru saja memuat data saya sebagai xy untuk kesederhanaan untuk memeriksanya. Butuh sedikit waktu untuk berjalan seperti yang Anda sebutkan tetapi tampaknya telah melakukan semuanya dengan benar. Saya akan secara manual mengecek beberapa dengan peta GIS saya tetapi sejauh ini terlihat bagus. Terima kasih telah membantu saya mengatasi hal ini, sangat ingin belajar di GIS dan R dan saya berada di kurva belajar yang curam.
James
1
Saya mengedit jawaban untuk memberikan solusi dengan skalabilitas yang sangat meningkat. Sekarang mampu menangani jalur yang berisi jutaan titik.
whuber
1
Saya menjalankan kode asli dengan file titik 2000 entri yang masing-masing mengambil beberapa jam, seperti yang Anda katakan ada terlalu banyak titik ke titik lokasi yang tidak diperpanjang memperpanjang waktu pemrosesan. Hasil edit di atas terlihat seperti solusi yang rapi dan saya akan mencoba ini pada data yang sama dan melihat seberapa cepat itu. Terima kasih atas upaya memproduksi dan mengedit fungsinya.
James
1

Saya pikir yang terbaik adalah skrip sedikit rutin menggunakan ArcPy. Saya akan membuat sesuatu seperti pseudo-code ini:

Select all points sorted by location-id    
Iterate for each point:
    Select points by location using a distance (no need to create buffer geometry)
    Sort points by location-id
    Set a variable to the value of your reference id
    consecutive-counter = 0
        Iterate your selection:
            Is the location-id of the first (or next) point equal to variable + 1?
            if 'yes' increment consecutive-counter by 1
            Repeat until 'no'

Saya tidak yakin apa yang ingin Anda lakukan dengan informasi tersebut tetapi saya kira Anda bisa membuat bidang di tabel Anda dan memperbaruinya dengan hitungan poin berurutan (jika demikian, tambahkan bidang terlebih dahulu).

Saya akan merekomendasikan membuat lapisan fitur (seperti tampilan tabel database tetapi untuk fitur di Arc). Buat dua dari data asli dan buka kursor pembaruan pada set pertama yang menentukan jenis keseluruhan Anda (karena ESRI tidak memenuhi permintaan SQL penuh). Gunakan yang kedua untuk memilih berdasarkan lokasi dari dan membuka Kursor Pencarian pada set pilihan yang dihasilkan.

[EDIT SEBAGAI PERMINTAAN Jame] Kasar saja menggunakan Model Builder. Jika Anda belum pernah menggunakan Pembuat Model sebelumnya, yang harus Anda lakukan adalah klik kanan di arcToolbox. Pilih 'Tambah kotak Alat'. Klik kanan pada toolbox baru dan klik 'New-> model'. Setelah Anda memiliki jendela model baru, seret dan letakkan alat dan data yang Anda butuhkan ke jendela dan tautkan secara visual bersama-sama (menggunakan alat panah kecil). Ketika Anda sudah sejauh yang Anda bisa (Anda tidak akan dapat menambahkan kursor Anda di sini), gunakan opsi di Menu File Model Builder untuk mengekspor ke Python. Itu akan membuat Anda sebagian besar jalan ke sana. Ini adalah kode yang dibuat secara otomatis sehingga akan menjadi sedikit jahat tetapi fungsional. Kemudian gunakan tautan dalam jawaban saya di atas untuk memahami dan menambahkan kursor.

Jika Anda baru mengenal Python, jangan takut menulis kode! Python adalah bahasa scripting yang sangat mudah untuk mendapatkan hasil dari dengan cepat. Esri juga memiliki panduan tentang hal itu.

Jika Anda mengalami masalah dengan kode Anda, poskan ke forum ini dan minta bantuan. Ada BANYAK orang di sini yang dapat membantu. Satu peringatan - pastikan Anda menggunakan bantuan yang tepat dari ESRI. Mereka secara besar-besaran mengubah API Python antara versi 9.x dan 10 (masing-masing arcgisscripting dan arcpy). Jadi, jika Anda menggunakan ArcGIS 9.x, temukan tautan yang setara untuk menambang!

MappaGnosis
sumber
Ini seperti apa yang ingin saya lakukan. Namun, saat ini saya tidak menggunakan kode dalam ArcGIS, hanya memilih dari opsi yang telah ditentukan. Bagaimana saya mulai menggunakan / menghasilkan metode yang disarankan di atas? Saya ingin output berupa tabel baru atau bidang baru ditambahkan ke tabel dengan jumlah poin berturut-turut.
James
Lihat edit saya ke posting utama saya.
MappaGnosis
JTB, silakan masuk menggunakan akun yang sama yang Anda gunakan untuk mengirim pertanyaan ini sehingga Anda dapat mengirim komentar (Untuk membuatnya lebih mudah, saya menggabungkan akun JTB dengan akun James.)
whuber
Maaf tentang perubahan akun. Saya memposting pertanyaan asli sebagai pengguna baru tetapi kemudian saya tidak bisa kembali ke akun itu karena saya tidak punya kata sandi dll. Oleh karena itu saya membuat akun JTB lain yang akan saya gunakan mulai sekarang (semoga). Saya akan memulai pembuat model seperti yang disarankan oleh Sylvester, tetapi setelah tidak pernah menggunakannya sebelum saya perlu sedikit waktu untuk membiasakan diri dengannya dan untuk mencari tahu alat apa yang digunakan dll. Saya akan kembali dengan kemajuan dan pertanyaan. Terima kasih
James
Sylvester - Saya pikir saya mengerti prosesnya tetapi saya bingung untuk mengetahui alat mana yang benar-benar harus saya mulai. Jarak? Penyangga? Dekat? Saya bahkan tidak tahu apakah ada alat yang tepat untuk masalah ini yang akan melakukan apa yang telah disebutkan di atas. Saya ingin belajar tetapi sangat banyak pada awalnya.
James
1

Anda dapat menggunakan pembuat model di ArcGIS untuk menemukan nilai ID berurutan. Saya mengekspor model saya sebagai skrip python. Kode akan menghasilkan shp baru yang memiliki nilai ID berurutan. !INDO! adalah bidang ID dasar. Anda harus memperbarui jalur point2.shp, nama, dan nama bidang ID untuk cocok dengan kasus Anda.

# Import arcpy module
import arcpy


# Local variables:
point2_shp = "C:\\temp\\point2.shp"
point2_shp__2_ = "C:\\temp\\point2.shp"
point2_shp__4_ = "C:\\temp\\point2.shp"
Freq_dbf__2_ = "C:\\temp\\Freq.dbf"
point2_shp__5_ = "C:\\temp\\point2.shp"
point2__2_ = "C:\\temp\\point2.shp"
point2__4_ = "C:\\temp\\point2.shp"
Freq_dbf = "C:\\temp\\Freq.dbf"
PointConsecutive_shp = "C:\\temp\\PointConsecutive.shp"

# Process: Add Field
arcpy.AddField_management(point2_shp, "AUTOID", "LONG", "", "", "", "", "NON_NULLABLE", "NON_REQUIRED", "")

# Process: Calculate Field
arcpy.CalculateField_management(point2__2_, "AUTOID", "autoIncrement()", "PYTHON_9.3", "rec=0\\ndef autoIncrement():\\n global rec\\n pStart = 1 #adjust start value, if req'd \\n pInterval = 1 #adjust interval value, if req'd\\n if (rec == 0): \\n  rec = pStart \\n else: \\n  rec = rec + pInterval \\n return rec\\n")

# Process: Add Field (2)
arcpy.AddField_management(point2_shp, "DIFF", "LONG", "", "", "", "", "NON_NULLABLE", "NON_REQUIRED", "")

# Process: Calculate Field (2)
arcpy.CalculateField_management(point2__4_, "DIFF", "!ID! - !AUTOID!", "PYTHON_9.3", "")

# Process: Frequency
arcpy.Frequency_analysis(point2_shp__2_, Freq_dbf, "DIFF", "")

# Process: Join Field
arcpy.JoinField_management(point2_shp__4_, "DIFF", Freq_dbf__2_, "DIFF", "")

# Process: Select
arcpy.Select_analysis(point2_shp__5_, PointConsecutive_shp, "\"FREQUENCY\" >1")
artwork21
sumber
Saya tidak yakin apa yang dilakukan kode di atas dan bagaimana ia menjawab pertanyaan saya. Saya menghargai bantuan tetapi ini semua cukup baru bagi saya karena tidak pernah menggunakan Python atau pembuat model. Apakah saya mengubah bidang ID untuk setiap proses yang terdaftar ke ID dalam dataset?
James
@ James, Itu tergantung jika ID Anda berubah. Untuk menggunakan kode, cukup salin dan tempel kode di atas dan simpan ke file txt kosong. Perbarui kode untuk mencocokkan nama dan jalur point.shp Anda. Kemudian, ubah nama ID di bagian kode Calculate Field (2) untuk mencocokkan bidang ID point.shp Anda. Simpan file txt, dan di windows explorer beri nama file dengan ekstensi .py. Klik kanan file dan buka dengan python.exe untuk menguji.
artwork21
Idealnya, skrip ini bisa dicolokkan ke alat skrip, yang juga menangani buffering dan pemilihan fitur. help.arcgis.com/en/arcgisdesktop/10.0/help/index.html#/…
artwork21