Bagaimana cara meningkatkan kinerja ketika menggunakan kursor ArcGIS di Python dengan tabel besar?


10

Saya memiliki kelas fitur titik yang cukup besar dalam geodatabase file (~ 4 000 000 catatan). Ini adalah grid poin biasa dengan resolusi 100m.

Saya perlu melakukan semacam generalisasi pada layer ini. Untuk ini, saya membuat kotak baru di mana setiap titik terletak di tengah-tengah 4 poin "lama":

 *     *     *     *
    o     o     o
 *     *     *     *
    o     o     o
 *     *     *     *

[*] = titik dari kotak asli - [o] = titik dari kotak baru

Nilai atribut dari setiap titik baru dihitung berdasarkan nilai tertimbang dari 4 tetangganya di kisi lama. Saya kemudian mengulang semua titik dari grid baru saya dan, untuk masing-masing, saya loop pada semua titik dari grid lama saya, untuk menemukan tetangga (dengan membandingkan nilai X dan Y dalam tabel atribut). Setelah 4 tetangga ditemukan, kami keluar dari lingkaran.

Tidak ada kompleksitas metodologis di sini tetapi masalah saya adalah bahwa, berdasarkan tes pertama saya, skrip ini akan berlangsung selama berminggu-minggu untuk menyelesaikan ...

Apakah Anda melihat kemungkinan untuk membuatnya lebih efisien? Beberapa ide di atas kepala saya:

  • Buat indeks bidang X dan Y => Saya melakukan itu tetapi tidak melihat adanya perubahan kinerja yang signifikan
  • Lakukan kueri spasial untuk menemukan tetangga daripada berbasis atribut. Apakah itu benar-benar membantu? Apa fungsi spasial di ArcGIS yang harus dilakukan? Saya ragu bahwa, misalnya, buffering setiap titik baru akan terbukti lebih efisien
  • Ubah kelas fitur menjadi NumPy Array. Apakah itu membantu? Saya belum bekerja banyak dengan NumPy sejauh ini dan saya tidak akan suka menyelaminya kecuali seseorang mengatakan kepada saya itu mungkin sangat membantu mengurangi waktu pemrosesan
  • Ada yang lain?

Versi Arcmap apa yang Anda gunakan?
Martin

Sudahkah Anda mempertimbangkan PostGIS? Apakah itu pilihan?
Chad Cooper

Maaf saya lupa itu: ArcGIS 10.1 // Python 2.7
Stéphane Henriod

Tidak, PostGIS sayangnya bukan pilihan, tangan saya sayangnya cukup terikat di sini ... Paling-paling saya bisa menggunakan Oracle dengan fungsi SDE
Stéphane Henriod

Jawaban:


13

Bagaimana jika Anda memasukkan poin ke array numpy dan menggunakan cKDTree yang cerdik untuk mencari tetangga. Saya memproses awan titik LiDAR dengan banyak titik (> 20 juta) dalam beberapa MENIT menggunakan teknik ini. Ada dokumentasi di sini untuk kdtree dan di sini untuk konversi numpy. Pada dasarnya, Anda membaca x, y menjadi sebuah array, dan beralih ke setiap titik dalam indeks pencarian array poin dalam jarak tertentu (lingkungan) dari setiap titik. Anda dapat menggunakan indeks ini untuk kemudian menghitung atribut lainnya.


jawaban ini lebih baik dari pada saya
radouxju

Saya suka ide ini, tetapi saya tidak punya masalah pada workstation yang saya kerjakan (dan tidak ada hak admin). Jika saya berhasil menginstal paket ini, maka saya akan mencobanya
Stéphane Henriod

4

Saya menggunakan Barbarossa ... kursor yang curam itu lumpuh, jadi saya hanya menggunakannya untuk melintasi tabel atau kelas fitur tepat satu kali. Jika saya tidak bisa menyelesaikan pekerjaan dalam satu siklus, saya menggunakan kursor untuk mengisi beberapa jenis struktur data lainnya dan bekerja dengan itu.

Jika Anda tidak ingin repot dengan numpy, cukup buat kamus python sederhana tempat Anda menggunakan koordinat Anda sebagai tombol teks sederhana, dan isi atribut yang Anda butuhkan untuk perhitungan ke dalam daftar sebagai nilai dari item kamus.

Pada langkah kedua Anda dapat dengan mudah mendapatkan nilai-nilai yang Anda butuhkan untuk menghitung suatu poin hanya dengan mendapatkannya dari kamus Anda (yang sangat cepat, karena kamus memiliki halaman belakang item).


Saya sebenarnya menyukai ide Anda dengan kamus dan saya baru saja mengimplementasikannya. Ini memang bekerja jauh lebih baik ... sampai saya benar-benar menulis hasilnya dengan row.insertRow () ... Adakah yang tahu bagaimana saya dapat memperbaiki bagian ini juga?
Stéphane Henriod

Saya memiliki masalah yang sama di mana saya harus memilih sekitar 10.000 poin dari 14 juta. dan kemudian hapus. arcpy.cursors di mana hanya dapat menghapus sekitar 1 atau 2 poin per detik (!). jadi saya menginstal modul pyodbc untuk menghapusnya dengan Pernyataan SQL DELETE tunggal hanya dalam satu detik. MEMPERBARUI lebih dari SQL akan membawa Anda banyak perbaikan, selama Anda hanya ingin memodifikasi atribut ... namun Anda harus menginstal modul python tambahan ... tapi itu sepadan.
Jürgen Zornig

2

Untuk grid biasa, seharusnya jauh lebih efisien untuk bekerja dalam format raster. Ubah grid pertama Anda menjadi raster, Anda dapat melakukan resample pada resolusi yang sama menggunakan interpolator bilinear tetapi menggeser gambar output Anda sebesar 1/2 piksel dalam X dan Y, dan kembali lagi ke titik jika Anda masih perlu memiliki poin.

EDIT: untuk aturan keputusan yang rumit, Anda dapat mengonversi setiap bidang yang Anda butuhkan sebagai pita raster baru, lalu membuat empat salinan pita tersebut dan menggeser Anda raster dalam 4 arah dengan 1/2 piksel (+50, - 50), (+50, +50), (-50, -50) dan (-50, +50). Kemudian Anda bisa menggunakan aljabar peta biasa


Terima kasih saya sebenarnya telah memikirkan solusi ini tetapi saya tidak yakin apakah / bagaimana saya dapat mengimplementasikan perhitungan nilai baru jika dalam format raster. Biarkan saya jelaskan: untuk setiap titik baru (atau sel raster baru) saya perlu menghitung nilainya seperti itu: Saya mengambil nilai dari masing-masing tetangganya. Masing-masing nilai tersebut memiliki probabilitas untuk memberikan nilai tertentu ke titik baru. Misalnya, jika satu tetangga memiliki nilai 202, maka ia akan memberikan nilai 3 (dengan bobot 1) atau nilai 11 (dengan bobot 5). Kami kemudian merangkum semua 4 tetangga dan menemukan nilai baru ... Tidak yakin apakah ini sangat jelas ...
Stéphane Henriod

PS: perhitungan untuk menemukan nilai baru dapat, dalam beberapa kasus, didasarkan pada 2 atribut, bukan hanya satu, yang mungkin membuang pendekatan Raster
Stéphane Henriod

untuk jumlah tertimbang Anda, Anda hanya perlu dua raster: satu di mana Anda menguji ulang produk dari bobot dan nilai-nilai, yang kedua di mana Anda hanya menguji bobotnya. Jika Anda membagi yang pertama dengan yang kedua, Anda mendapatkan jumlah tertimbang Anda.
radouxju

1
@ StéphaneHenriod - sebagai saran, Anda dapat mempertimbangkan untuk mengedit pertanyaan untuk menambahkan spesifikasi tambahan ini. Mengingat pertanyaan awal, saya pikir jawaban ini masuk akal, tetapi dengan informasi baru ini, jawaban Barbarossa terlihat bagus.
nicksan

2

Terima kasih semuanya atas bantuan Anda!

Saya akhirnya menemukan cara yang sangat non-pythonic untuk menyelesaikan masalah ini ... Apa yang sebenarnya mengambil waktu komputasi paling banyak adalah untuk menemukan 4 tetangga dari setiap titik. Daripada menggunakan atribut X dan Y (baik dengan kursor arcpy atau dalam struktur data lain, seperti python ditionary), saya akhirnya menggunakan alat ArcGIS Generate near table . Saya menganggap ini mengambil keuntungan dari indeks spasial dan kinerja jelas jauh lebih tinggi, tanpa saya harus menerapkan indeks sendiri.


0

Masalah dengan kursor adalah bahwa Anda dapat menggilirnya hanya dengan satu cara dan Anda tidak dapat kembali. Meskipun tidak disarankan, Anda dapat mengisi feautres ke dalam struktur jika Anda berencana untuk mengunjungi kembali.

Jika Anda dapat memproses fitur Anda dalam satu lingkaran, saya sarankan mengaktifkan daur ulang. Ini adalah parameter pada fungsi class pencarian Anda yang memungkinkan python untuk menggunakan kembali memori yang dialokasikan oleh fitur lama dan membuat melintasi fitur dalam kursor lebih cepat. Anda dapat memproses kisi Anda 80% lebih cepat.

Masalahnya adalah Anda tidak dapat mengaktifkan daur ulang jika Anda berencana untuk menyimpan fitur yang diambil dari kursor.


Saya ingin menjelajahi subjek "daur ulang kursor" ini tetapi tidak dapat menemukan dokumentasi tentang Bantuan ESRI. Apakah Anda memiliki tautan? Kursor Pencarian tidak memiliki parameter daur ulang. Select_by_Attribute tidak memiliki parameter seperti itu. Saya tidak melihat apa pun di ENV.
klewis

Saya menulis sebuah artikel beberapa waktu lalu husseinnasser.com/2009/08/when-to-use-recycling-cursor.html?m=1
hnasr

1
Saya tidak berpikir "menggunakan kembali kursor" tersedia melalui ArcPy, hanya dengan Arcobjects inti.
klewis
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.