Lagi

Menemukan tetangga urutan pertama dari 200k poligon secara efisien

Menemukan tetangga urutan pertama dari 200k poligon secara efisien


Untuk setiap satu dari 208.781 kelompok blok Sensus, saya ingin mengambil ID FIPS dari semua tetangga urutan pertama. Saya memiliki semua batas TIGER yang diunduh dan digabungkan menjadi satu shapefile 1GB.

Saya mencoba skrip ArcPython yang menggunakan SelectLayerByLocation untuk BOUNDARY_TOUCHES pada intinya, tetapi dibutuhkan lebih dari 1 detik untuk setiap grup blok yang lebih lambat dari yang saya inginkan. Ini bahkan setelah saya membatasi pencarian SelectLayerByLocation untuk memblokir grup dalam keadaan yang sama. Saya menemukan skrip ini, tetapi juga menggunakan SelectLayerByLocation secara internal sehingga tidak lebih cepat.

Solusinya tidak harus berbasis Arc--Saya terbuka untuk paket lain, meskipun saya paling nyaman coding dengan Python.


Jika Anda memiliki akses ke ArcGIS 10.2 untuk Desktop, atau mungkin sebelumnya, maka saya pikir alat Polygon Neighbors (Analisis) yang:

Membuat tabel dengan statistik berdasarkan kedekatan poligon (tumpang tindih, tepi bertepatan, atau simpul).

dapat membuat tugas ini lebih mudah sekarang.


Untuk solusi menghindari ArcGIS, gunakan pysal. Anda bisa mendapatkan bobot langsung dari shapefile menggunakan:

w = pysal.rook_from_shapefile("… /pysal/examples/columbus.shp")

atau

w = pysal.queen_from_shapefile("… /pysal/examples/columbus.shp")

Buka dokumen untuk info lebih lanjut.


Hanya pembaruan. Setelah mengikuti saran Whuber, saya menemukan bahwa Generate Spatial Weights Matrix hanya menggunakan loop dan kamus Python untuk menentukan tetangga. Saya mereproduksi proses di bawah ini.

Bagian pertama loop melalui setiap simpul dari setiap grup blok. Ini membuat kamus dengan koordinat titik sebagai kunci dan daftar ID grup blok yang memiliki titik pada koordinat itu sebagai nilainya. Perhatikan bahwa ini memerlukan kumpulan data yang rapi secara topologi, karena hanya simpul/simpul yang tumpang tindih sempurna yang akan terdaftar sebagai hubungan tetangga. Untungnya shapefile kelompok blok TIGER Biro Sensus baik-baik saja dalam hal ini.

Bagian kedua mengulang setiap simpul dari setiap grup blok lagi. Itu membuat kamus dengan ID grup blok sebagai kunci dan ID tetangga grup blok itu sebagai nilainya.

# Buat kamus koordinat titik : [… ,ID,… ] BlockGroupVertexDictionary = {} BlockGroupCursor = arcpy.SearchCursor(BlockGroups.shp) BlockGroupDescription = arcpy.Describe(BlockGroups.shp) BlockGroupShapeFieldName. #For every blockGroupsDescription = BlockGroupsDescribe(BlockGroups.shp) BlockGroupShapeFieldName = BlockGroupsDescription untuk setiap blockGroupsDescription BlockGroupItem di BlockGroupCursor : BlockGroupID = BlockGroupItem.getValue("BKGPIDFP00") BlockGroupFeature = BlockGroupItem.getValue(BlockGroupShapeFieldName) untuk BlockGroupPart di BlockGroupFeature: #Untuk setiap vertex... untuk BlockGroup lubangPoint is... if BlockGroupPoint: #Buat versi string dari koordinat PointText = str(BlockGroupPoint.X)+str(BlockGroupPoint.Y) #Jika koordinat sudah ada di kamus, tambahkan ID BG ini jika PointText di BlockGroupVertexDictionary: BlockGroupVertexDictionary[PointText].append(BlockGroupID) #Jika koordinat belum ada dalam kamus, buat daftar baru dengan ID BG ini: BlockGroupVertexDictionary[Poi ntText] = [BlockGroupID] del BlockGroupItem del BlockGroupCursor #Buat kamus ID : [… ,neighbors,… ] BlockGroupNeighborDictionary = {} BlockGroupCursor = arcpy.SearchCursor(BlockGroups.shp) BlockGroupDescribe. BlockGroupDescription = arcpy. .ShapeFieldName #Untuk setiap grup blok untuk BlockGroupItem di BlockGroupCursor: ListOfBlockGroupNeighbors = [] BlockGroupID = BlockGroupItem.getValue("BKGPIDFP00") BlockGroupFeature = BlockGroupItem.getValue(BlockGroupFeaturePart) untuk BlockForGroupGroupPart untuk BlockForGroupField itu ada (dan bukan penanda lubang interior)… jika BlockGroupPoint: #Buat versi string dari koordinat PointText = str(BlockGroupPoint.X)+str(BlockGroupPoint.Y) if PointText di BlockGroupVertexDictionary: #Dapatkan daftar grup blok yang memiliki titik ini sebagai a vertex NeighborIDList = BlockGroupVertexDictionary[PointText] untuk NeighborID di NeighborIDList: #Jangan iklan d jika BG ini sudah ada dalam daftar tetangga jika NeighborID di ListOfBGNeighbors: lulus #Tambahkan ke daftar tetangga (asalkan bukan itu sendiri) elif NeighborID != BlockGroupID: ListOfBGNeighbors.append(NeighborID) #Simpan daftar tetangga di objek blockgroup di kamus BlockGroupNeighborDictionary[BlockGroupID] = ListOfBGNeighbors del BlockGroupItem del BlockGroupCursor del BlockGroupVertexDictionary

Di belakang saya menyadari saya bisa menggunakan metode yang berbeda untuk bagian kedua yang tidak memerlukan perulangan melalui shapefile lagi. Tapi inilah yang saya gunakan, dan ini bekerja cukup baik bahkan untuk 1000-an grup blok sekaligus. Saya belum mencoba melakukannya dengan seluruh AS, tetapi dapat dijalankan untuk seluruh negara bagian.


Alternatifnya mungkin menggunakan PostgreSQL dan PostGIS. Saya telah mengajukan beberapa pertanyaan tentang cara melakukan perhitungan serupa di situs ini:

Saya menemukan ada kurva belajar yang curam untuk mengetahui bagaimana berbagai bagian perangkat lunak cocok bersama, tetapi saya merasa luar biasa untuk melakukan perhitungan pada lapisan vektor besar. Saya telah menjalankan beberapa perhitungan tetangga terdekat pada jutaan poligon dan itu lebih cepat dibandingkan dengan ArcGIS.


Hanya beberapa komentar… metode esri/ArcGIS saat ini menggunakan kamus untuk menyimpan informasi tetapi perhitungan inti dilakukan dalam C++ menggunakan Polygon Neighbors Tool. Alat ini menghasilkan Tabel yang berisi informasi kedekatan serta atribut opsional seperti panjang batas bersama. Anda dapat menggunakan Alat Matriks Bobot Spasial Hasilkan jika Anda ingin menyimpan dan kemudian menggunakan kembali info tersebut berulang kali. Anda juga dapat menggunakan fungsi ini di WeightsUtilities untuk menghasilkan kamus [akses acak] dengan info kedekatan:

contDict = polygonNeighborDict(inputFC, masterField, contiguityType = "ROOK")

di mana inputFC = semua jenis kelas fitur poligon, masterField adalah bidang "ID unik" dari bilangan bulat dan contiguityType di {"ROOK", "QUEEN"}.

Ada upaya di esri untuk melewati aspek tabular untuk pengguna Python dan langsung ke iterator yang akan membuat banyak kasus penggunaan jauh lebih cepat. PySAL dan paket spdep di R adalah alternatif yang fantastis [lihat jawaban radek]. Saya pikir Anda diharuskan menggunakan shapefile sebagai format data dalam paket-paket ini yang selaras dengan format input utas ini. Tidak yakin bagaimana mereka menangani poligon yang tumpang tindih serta poligon di dalam poligon. Hasilkan SWM serta fungsi yang saya jelaskan akan menghitung hubungan spasial tersebut sebagai Tetangga "BENteng" DAN "RATU".


Tonton videonya: Pengukuran Poligon Tertutup Menggunakan Total Station