Saya dapat melihat beberapa hal yang mungkin menyebabkan skrip Anda lambat. Hal yang mungkin sangat lambat adalah arcpy.CalculateField_management()
fungsinya. Anda harus menggunakan kursor, dengan beberapa besaran lebih cepat. Juga, Anda mengatakan Anda menggunakan ArcGIS Desktop 10.3.1, tetapi Anda menggunakan kursor gaya lama ArcGIS 10.0, yang juga jauh lebih lambat.
Operasi min () bahkan pada daftar 200K akan cukup cepat. Anda dapat memverifikasi ini dengan menjalankan cuplikan kecil ini; itu terjadi dalam sekejap mata:
>>> min(range(200000)) # will return 0, but is still checking a list of 200,000 values very quickly
Lihat apakah ini lebih cepat:
import arcpy
fc = arcpy.env.workspace = arcpy.GetParameterAsText(0)
Xfield = "XKoordInt"
with arcpy.da.SearchCursor(fc, [Xfield]) as rows:
ListVal = [r[0] for r in rows]
value = min(ListVal) - 20
print value
# now update
with arcpy.da.UpdateCursor(fc, [Xfield, 'Matrix_Z']) as rows:
for r in rows:
if r[0] is not None:
r[1] = (r[0] - value) / 20.0
rows.updateRow(r)
EDIT:
Saya menjalankan beberapa tes waktu dan seperti yang saya duga, kalkulator lapangan mengambil hampir dua kali lipat panjang kursor gaya baru. Menariknya, kursor gaya lama ~ 3x lebih lambat dari kalkulator lapangan. Saya membuat 200.000 poin acak dan menggunakan nama bidang yang sama.
Fungsi dekorator digunakan untuk menentukan waktu setiap fungsi (mungkin ada sedikit overhead dalam pengaturan dan meruntuhkan fungsi, jadi mungkin modul timeit akan sedikit lebih akurat untuk menguji snippet).
Inilah hasilnya:
Getting the values with the old style cursor: 0:00:19.23
Getting values with the new style cursor: 0:00:02.50
Getting values with the new style cursor + an order by sql statement: 0:00:00.02
And the calculations:
field calculator: 0:00:14.21
old style update cursor: 0:00:42.47
new style cursor: 0:00:08.71
Dan di sini adalah kode yang saya gunakan (memecah semuanya menjadi fungsi individu untuk menggunakan timeit
dekorator):
import arcpy
import datetime
import sys
import os
def timeit(function):
"""will time a function's execution time
Required:
function -- full namespace for a function
Optional:
args -- list of arguments for function
kwargs -- keyword arguments for function
"""
def wrapper(*args, **kwargs):
st = datetime.datetime.now()
output = function(*args, **kwargs)
elapsed = str(datetime.datetime.now()-st)[:-4]
if hasattr(function, 'im_class'):
fname = '.'.join([function.im_class.__name__, function.__name__])
else:
fname = function.__name__
print'"{0}" from {1} Complete - Elapsed time: {2}'.format(fname, sys.modules[function.__module__], elapsed)
return output
return wrapper
@timeit
def get_value_min_old_cur(fc, field):
rows = arcpy.SearchCursor(fc)
return min([r.getValue(field) for r in rows])
@timeit
def get_value_min_new_cur(fc, field):
with arcpy.da.SearchCursor(fc, [field]) as rows:
return min([r[0] for r in rows])
@timeit
def get_value_sql(fc, field):
"""good suggestion to use sql order by by dslamb :) """
wc = "%s IS NOT NULL"%field
sc = (None,'Order By %s'%field)
with arcpy.da.SearchCursor(fc, [field]) as rows:
for r in rows:
# should give us the min on the first record
return r[0]
@timeit
def test_field_calc(fc, field, expression):
arcpy.management.CalculateField(fc, field, expression, 'PYTHON')
@timeit
def old_cursor_calc(fc, xfield, matrix_field, value):
wc = "%s IS NOT NULL"%xfield
rows = arcpy.UpdateCursor(fc, where_clause=wc)
for row in rows:
if row.getValue(xfield) is not None:
row.setValue(matrix_field, (row.getValue(xfield) - value) / 20)
rows.updateRow(row)
@timeit
def new_cursor_calc(fc, xfield, matrix_field, value):
wc = "%s IS NOT NULL"%xfield
with arcpy.da.UpdateCursor(fc, [xfield, matrix_field], where_clause=wc) as rows:
for r in rows:
r[1] = (r[0] - value) / 20
rows.updateRow(r)
if __name__ == '__main__':
Xfield = "XKoordInt"
Mfield = 'Matrix_Z'
fc = r'C:\Users\calebma\Documents\ArcGIS\Default.gdb\Random_Points'
# first test the speed of getting the value
print 'getting value tests...'
value = get_value_min_old_cur(fc, Xfield)
value = get_value_min_new_cur(fc, Xfield)
value = get_value_sql(fc, Xfield)
print '\n\nmin value is {}\n\n'.format(value)
# now test field calculations
expression = "(!XKoordInt!-{0})/20".format(value)
test_field_calc(fc, Xfield, expression)
old_cursor_calc(fc, Xfield, Mfield, value)
new_cursor_calc(fc, Xfield, Mfield, value)
Dan akhirnya, inilah hasil cetak sebenarnya dari konsol saya.
>>>
getting value tests...
"get_value_min_old_cur" from <module '__main__' from 'C:/Users/calebma/Desktop/speed_test2.py'> Complete - Elapsed time: 0:00:19.23
"get_value_min_new_cur" from <module '__main__' from 'C:/Users/calebma/Desktop/speed_test2.py'> Complete - Elapsed time: 0:00:02.50
"get_value_sql" from <module '__main__' from 'C:/Users/calebma/Desktop/speed_test2.py'> Complete - Elapsed time: 0:00:00.02
min value is 5393879
"test_field_calc" from <module '__main__' from 'C:/Users/calebma/Desktop/speed_test2.py'> Complete - Elapsed time: 0:00:14.21
"old_cursor_calc" from <module '__main__' from 'C:/Users/calebma/Desktop/speed_test2.py'> Complete - Elapsed time: 0:00:42.47
"new_cursor_calc" from <module '__main__' from 'C:/Users/calebma/Desktop/speed_test2.py'> Complete - Elapsed time: 0:00:08.71
>>>
Sunting 2: Baru saja memposting beberapa tes yang diperbarui, saya menemukan sedikit cacat pada timeit
fungsi saya .