Tôi có thể thấy một số điều có thể khiến kịch bản của bạn bị chậm. Điều có khả năng rất chậm là arcpy.CalculateField_management()
chức năng. Bạn nên sử dụng một con trỏ, nó sẽ nhanh hơn vài độ. Ngoài ra, bạn cho biết bạn đang sử dụng ArcGIS Desktop 10.3.1, nhưng bạn đang sử dụng các con trỏ kiểu ArcGIS 10.0 cũ, tốc độ cũng chậm hơn nhiều.
Thao tác min () ngay cả trong danh sách aK 200K sẽ khá nhanh. Bạn có thể xác minh điều này bằng cách chạy đoạn mã nhỏ này; nó xảy ra trong chớp mắt:
>>> min(range(200000)) # will return 0, but is still checking a list of 200,000 values very quickly
Xem nếu điều này là nhanh hơn:
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)
BIÊN TẬP:
Tôi đã chạy một số bài kiểm tra thời gian và như tôi nghi ngờ, máy tính trường mất gần gấp đôi con trỏ kiểu mới. Thật thú vị, con trỏ kiểu cũ chậm hơn ~ 3 lần so với máy tính trường. Tôi đã tạo ra 200.000 điểm ngẫu nhiên và sử dụng cùng tên trường.
Một chức năng trang trí được sử dụng để thời gian mỗi chức năng (có thể có một số chi phí nhỏ trong việc thiết lập và phá đổ các chức năng, như vậy có lẽ các timeit mô-đun sẽ là một chút chính xác hơn để đoạn thử nghiệm).
Đây là kết quả:
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
Và đây là đoạn mã tôi đã sử dụng (chia mọi thứ thành các hàm riêng lẻ để sử dụng trình timeit
trang trí):
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)
Và cuối cùng, đây là những gì bản in thực tế là từ bảng điều khiển của tôi.
>>>
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
>>>
Chỉnh sửa 2: Chỉ cần đăng một số bài kiểm tra cập nhật, tôi thấy một lỗ hổng nhỏ với timeit
chức năng của mình .