ฉันเห็นหลายสิ่งที่อาจทำให้สคริปต์ของคุณช้า สิ่งที่น่าจะช้ามากคือarcpy.CalculateField_management()
ฟังก์ชั่น คุณควรใช้เคอร์เซอร์มันจะเร็วขึ้นหลายขนาด นอกจากนี้คุณบอกว่าคุณกำลังใช้ ArcGIS Desktop 10.3.1 แต่คุณกำลังใช้เคอร์เซอร์สไตล์ ArcGIS 10.0 ซึ่งช้ากว่ามากเช่นกัน
การดำเนินการขั้นต่ำ () แม้ในรายการ 200K จะค่อนข้างเร็ว คุณสามารถตรวจสอบสิ่งนี้ได้ด้วยการเรียกใช้ตัวอย่างขนาดเล็กนี้ มันเกิดขึ้นในพริบตา:
>>> min(range(200000)) # will return 0, but is still checking a list of 200,000 values very quickly
ดูว่านี่เร็วกว่าไหม:
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)
แก้ไข:
ฉันวิ่งทดสอบเวลาและตามที่ฉันสงสัยเครื่องคิดเลขภาคสนามใช้เวลาเกือบสองเท่าของเคอร์เซอร์สไตล์ใหม่ ที่น่าสนใจเคอร์เซอร์แบบเก่านั้นช้ากว่าเครื่องคิดเลขภาคสนามประมาณ 3 เท่า ฉันสร้าง 200,000 คะแนนสุ่มและใช้ชื่อฟิลด์เดียวกัน
ฟังก์ชั่นมัณฑนากรถูกใช้เพื่อตั้งเวลาแต่ละฟังก์ชั่น (อาจจะมีค่าใช้จ่ายเล็กน้อยในการตั้งค่าและการทำลายฟังก์ชั่นดังนั้นโมดูลtimeitอาจจะแม่นยำมากขึ้นเล็กน้อยในการทดสอบตัวอย่าง)
นี่คือผลลัพธ์:
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
และนี่คือรหัสที่ฉันใช้ (ทำทุกอย่างลงไปในแต่ละฟังก์ชั่นเพื่อใช้timeit
มัณฑนากร):
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)
และในที่สุดนี่คือสิ่งที่พิมพ์ออกมาจริงจากคอนโซลของฉัน
>>>
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
>>>
แก้ไข 2: เพิ่งโพสต์การทดสอบที่อัปเดตบางอย่างฉันพบข้อบกพร่องเล็กน้อยกับtimeit
ฟังก์ชั่นของฉัน