스크립트 속도가 느려질 수있는 몇 가지 사항이 있습니다. 매우 느려질 수있는 것은 arcpy.CalculateField_management()
기능입니다. 커서를 사용하면 몇 배 빠릅니다. 또한 ArcGIS Desktop 10.3.1을 사용하고 있다고 말했지만 이전 ArcGIS 10.0 스타일 커서를 사용하고 있으며 속도가 훨씬 느립니다.
200K 목록에서도 min () 작업이 매우 빠릅니다. 이 작은 스 니펫을 실행하여이를 확인할 수 있습니다. 그것은 눈 깜박임에서 발생합니다 :
>>> 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 개의 임의의 점을 만들고 동일한 필드 이름을 사용했습니다.
데코레이터 기능을 사용하여 각 기능의 시간을 정했습니다 (기능 설정 및 해제시 약간의 오버 헤드가 발생할 수 있으므로 시간 모듈이 스 니펫을 테스트하는 데 약간 더 정확할 수 있음).
결과는 다음과 같습니다.
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
기능에 약간의 결함이 있음을 발견했습니다 .