Mengapa skrip ArcPy lambat?

12

Saya punya skrip arcpy sederhana untuk memperbarui bidang dalam bentuk titik dengan info dari fitur poligon yang ada di dalamnya. Dibutuhkan 9 menit untuk menghasilkan 100 poin di arcpy, tetapi join spasial di arcmap adalah instan. Saya yakin ada cara cepat untuk menyelesaikan masalah ini. Bisakah seseorang mengarahkan saya ke arah yang benar?

import took 0:00:07.085000
extent took 0:00:05.991000
one pt loop took 0:00:03.780000
one pt loop took 0:00:03.850000
one pt loop took 0:00:03.791000


import datetime
t1 = datetime.datetime.now()
import arcpy
t2 = datetime.datetime.now()
print "import took %s" %  ( t2-t1)
#set up environment
arcpy.env.workspace = "data\\"
arcpy.env.overwriteOutput = True

desc = arcpy.Describe("parcels.shp")
ext = desc.Extent
extent = (ext.XMin,ext.XMax,ext.YMin,ext.YMax)
t3 = datetime.datetime.now()
print "extent took %s" %  (t3 -t2)
fc = arcpy.CreateRandomPoints_management("", "malls.shp", "", ext, 100, "", "POINT", "")
arcpy.AddField_management("malls.shp", 'ParcelID', 'LONG')

rows = arcpy.UpdateCursor('malls.shp',"","",'ParcelID')
for row in rows:
    t4 = datetime.datetime.now()
    pt = row.Shape.getPart()
    for polyrow in arcpy.SearchCursor('parcels.shp'):
        t6 = datetime.datetime.now()
        poly = polyrow.getValue('Shape')
        if extent[0]<pt.X<extent[1] and extent[2]<pt.Y<extent[3]:
            if poly.contains(pt):
                print "works"
                row.ParcelID = polyrow.Parcels_ID
                rows.updateRow(row)
                break #we can stop looking for matches since
        t7 = datetime.datetime.now()
        "a full poly loop took %s" % (t7-t6)
    t5 = datetime.datetime.now()
    print "one pt loop took %s" % (t5-t4)


print datetime.datetime.now() -t1
EmdyP
sumber
4
Anda berada di versi ArcGIS mana? 10.1 menambahkan arcpy.damodul (Akses Data) dengan versi kursor yang lebih cepat.
blah238

Jawaban:

20

Jika Anda perlu membuat kursor kedua parcels.shp, lakukan di luar loop untuk kursor pertama Anda. Seperti adanya, skrip Anda membuat objek kursor baru untuk setiap baris malls.shpyang membuat Anda harus membayar semua waktu pemrosesan.

...
rows = arcpy.UpdateCursor('malls.shp',"","",'ParcelID')
polyrows = arcpy.SearchCursor('parcels.shp')
for row in rows:
    t4 = datetime.datetime.now()
    pt = row.Shape.getPart()
    for polyrow in polyrows:
...
Jason
sumber
Ini persis seperti itu. Terima kasih. dan kemudian saya menggunakan .reset () pada kursor kedua saya untuk setiap kali saya ingin melewatinya? Sepertinya hanya melewati kursor 1 kali sekarang.
EmdyP
Hmm, Anda tidak perlu mengatur ulang baris. Pastikan Anda menghapus objek baris dan objek kursor di akhir skrip. Hal-hal lucu dapat terjadi jika Anda tidak melakukannya.
Jason
Saya pikir kursor loop dalam tidak perlu diatur ulang setiap kali jika Anda pergi rute ini. Lihat jawaban saya untuk alternatif.
blah238
10

Masalah dengan jawaban @ Jason (dan pendekatan awal Anda) adalah bahwa ia tidak mengambil keuntungan dari indeks spasial dan membutuhkan loop dua-kursor yang bersarang yang akan menjadi lebih lambat secara eksponensial ketika jumlah poin meningkat.

Alur kerja alternatif yang mungkin lebih cepat sementara masih membiarkan Anda memperbarui kelas fitur titik di tempat (Penggabungan Tata Ruang hanya menghasilkan kelas fitur baru, bukan memperbarui yang sudah ada) mungkin untuk:

  1. Gunakan Spatial Join untuk membuat kelas fitur menengah (mungkin dalam memori)
  2. Gunakan Tambah Gabung untuk bergabung dengan kelas fitur menengah ke kelas fitur titik yang ada
  3. Gunakan Calculate Field atau UpdateCursor untuk menyalin nilai-nilai di bidang yang digabungkan ke bidang di kelas fitur titik yang ada.
blah238
sumber
2
Saya suka alur kerja alternatif ini - Saya suka itu meskipun saya tidak mengajukan pertanyaan, saya masih belajar cara-cara baru untuk melakukan sesuatu di sini.
Jason