データアクセスモジュールは、ArcGISバージョン10.1で導入されました。ESRIは、データアクセスモジュールを次のように記述します(ソース):
データアクセスモジュールarcpy.daは、データを操作するためのPythonモジュールです。編集セッションの制御、編集操作、改善されたカーソルサポート(高速パフォーマンスを含む)、テーブルとフィーチャクラスのNumPy配列との変換、バージョン管理、レプリカ、ドメイン、サブタイプのワークフローのサポートが可能になります。
ただし、カーソルのパフォーマンスが以前の世代のカーソルよりも向上した理由に関する情報はほとんどありません。
添付の図は、新しいda
メソッドUpdateCursorと古いUpdateCursorメソッドのベンチマークテストの結果を示しています。基本的に、スクリプトは次のワークフローを実行します。
- ランダムポイント(10、100、1000、10000、100000)を作成します
- 正規分布からランダムにサンプリングし、カーソルを使用してランダムポイント属性テーブルの新しい列に値を追加します
- 新しいUpdateCursorメソッドと古いUpdateCursorメソッドの両方について、各ランダムポイントシナリオを5回繰り返し、平均値をリストに書き込みます
- 結果をプロットする
da
カーソルのパフォーマンスを図に示されている程度まで改善するために、更新カーソルを使用して舞台裏で何が行われていますか?
import arcpy, os, numpy, time
arcpy.env.overwriteOutput = True
outws = r'C:\temp'
fc = os.path.join(outws, 'randomPoints.shp')
iterations = [10, 100, 1000, 10000, 100000]
old = []
new = []
meanOld = []
meanNew = []
for x in iterations:
arcpy.CreateRandomPoints_management(outws, 'randomPoints', '', '', x)
arcpy.AddField_management(fc, 'randFloat', 'FLOAT')
for y in range(5):
# Old method ArcGIS 10.0 and earlier
start = time.clock()
rows = arcpy.UpdateCursor(fc)
for row in rows:
# generate random float from normal distribution
s = float(numpy.random.normal(100, 10, 1))
row.randFloat = s
rows.updateRow(row)
del row, rows
end = time.clock()
total = end - start
old.append(total)
del start, end, total
# New method 10.1 and later
start = time.clock()
with arcpy.da.UpdateCursor(fc, ['randFloat']) as cursor:
for row in cursor:
# generate random float from normal distribution
s = float(numpy.random.normal(100, 10, 1))
row[0] = s
cursor.updateRow(row)
end = time.clock()
total = end - start
new.append(total)
del start, end, total
meanOld.append(round(numpy.mean(old),4))
meanNew.append(round(numpy.mean(new),4))
#######################
# plot the results
import matplotlib.pyplot as plt
plt.plot(iterations, meanNew, label = 'New (da)')
plt.plot(iterations, meanOld, label = 'Old')
plt.title('arcpy.da.UpdateCursor -vs- arcpy.UpdateCursor')
plt.xlabel('Random Points')
plt.ylabel('Time (minutes)')
plt.legend(loc = 2)
plt.show()