ArcPy でのフィーチャ データの利用

Document created by shinji_katayaesrij-esridist Employee on Apr 23, 2019Last modified by yuki_ozawaesrij-esridist on Apr 24, 2019
Version 7Show Document
  • View in full screen mode

はじめに:

 

先月の3/5 ~ 3/8 に米国で行われた「Esri Developer Summit 2019 」のテクニカル セッション 242本分の動画が、先々週から公開が始まっています( Esri 2019 Developer Summit Tech Sessions )。 その中の一部のものは、スライド やデモ で利用しているコードがGitHub 上で公開されており、開発する際のヒントになるかと思います。

今回の記事では、「Python Working with Feature Data」のタイトルで発表されていたセッションの内容を、スライドに沿う形で紹介していきます。ArcPy でのフィーチャ データ, テーブルの操作に関する内容がコンパクトにまとまっていますので、ArcPy でデータを操作したい方は必見の内容かと思います。

この記事の見出しは、スライドのタイトルに対応しています。また、コードリーディングを重視して、原文のままにしているものもありますので、ご了承ください。

 

 

スライド:

 

Cursors

 

  • Cursors はレコード単位、フィーチャ単位でのアクセスを提供
    • さまざまなワーク フローで基本的には必要
         SearchCursor | 読み取り専用のアクセスに利用
         UpdateCursor | 行の更新、もしくは削除に利用
         InsertCursor | 行の挿入に利用

  • 2つの実装がある
    • arcpy.da cursors と "Classic" cursors
    • どっちを使う? 昔作ったコードを持っていない限り、arcpy.da cursors を使うのを推奨

 

 

Table basics

 

※スライドのセル色の説明

  • 黄色セル:行
  • 緑色セル:列
  • 水色セル:Geometry は Shape 列に格納されている(例ではPoint 型のジオメトリ)

 

 

Cursors

 

  • arcpy.da cursors は lists や tuples を使用
    • Row values には index を使ってアクセス可能

 

fields = ['field1', 'field2']
cursor = arcpy.da.InsertCursor(table, fields)
cursor.insertRow([1, 10])

 

  • ”Classic” cursors
    • 10.1 より前の scripts の例
    • Row objects を利用
    • Row values はsetValue, getValue を使って操作
cursor = arcpy.InsertCursor(table)
row = cursor.newRow()
row.setValue("field1", 1)
row.setValue("field2", 10)
cursor.insertRow(row)

 

with statemantes

 

  • arcpy.da Cusors は with statements(with構文)をサポート
with arcpy.da.SearchCursor(table, field) as cursor:
    for row in cursor:
        print row[0]

 

  • with statements(with構文)
    • python ではwith statements はコンテキストマネージャー
    • Locks が発生するような状況でのスコープを制御
    • コードが明快

 

 

Demo: Cursors

 

  • GitHub 上の「demo_1_cursor.py」のコードはこちら

 

 

More on cursors

  • Row values にはindex を使ってアクセス
  • パフォーマンスはよいが、コードの可読性は良くない
with arcpy.da.SearchCursor(table, fields) as cursor:
    for row in cursor:
        print(row[17]) #index 17 is RoadName field

 

  • あるいは、すぐにディクショナリに変換可能
    • generator function で Wrap すると、name でアクセス可能
      def row_as_dict(cursor):
          for row in cursor:
              yield dict(zip(cursor.fields, row))
             
      with arcpy.da.SearchCursor(table, fields) as cursor:
          for row in row_as_dict(cursor):
              print(row['RoadName'])

 

 

Fields and tokens

 

  • よいパフォーマンス のためには必要な fields を利用
    • 全ての fields を "*" で指定する方法は、パフォーマンスのためには非推奨

  • tokens も利用可能
    • これもアクセスしたい token でアクセスするのがよい

 

# tokens の例
'OID@'
'SHAPE@XY'
'SHAPE@TRUECENTROID'
'SHAPE@X'
'SHAPE@Y'
'SHAPE@Z'
'SHAPE@M'
'SHAPE@JSON'
'SHAPE@WKB'
'SHAPE@WKT'
'SHAPE@'
'SHAPE@AREA'
'SHAPE@LENGTH'

 

 

Editor class

 

  • トランザクションを管理するために編集セッションと編集操作を使用する
  • 編集は保存され永久に適用されるまで一時的なもの
  • 変更を保存せずに編集セッションを終了可能

 

  • いつ利用する必要がある?
    • トポロジー, ジオメトリ ネットワーク のフィーチャ を編集する場合
    • エンタープライズ ジオデータベース のバージョン対応データを操作する場合
    • クラス エクステンション のいくつかのオブジェクトやフィーチャ クラス を操作する場合

 

 

Editor using a with statement

 

  • Editorはwith構文 をサポート
  • 適切な開始処理、停止処理、および中止の処理

 

with arcpy.da.Editor(workspace) as edit:
    # your edits

 

※スライド上のオレンジ色の文字の説明

  • as edit: ← 編集セッションを開いて、編集操作を開始
  • # your edits のスコープで
    • Exception - 操作のキャンセル, 編集セッションが保存せずに閉じられた場合
    • No Exception - 操作の終了, 保存, 編集セッションを閉じる場合

Editor class

 

  • Editor class は編集セッションと操作をするためのメソッドも含まれている
# Start an edit session
edit = arcpy.da.Editor(workspace)
   
# Edit session is started without an undo/redo stach
# for versioned data
edit.startEditing(False, True)
   
# Start an edit operation
edit.startOperation()
   
# Edits
   
# Stop the edit operation
edit.stopOperation()
   
# Stop the edit session and save changes
edit.stopEditing(True)

 

# Editor methods

startEditing ({with_undo}, {multiuser_mode})

stopEditing(save_changes)

startOperation()

stopOperation()

abortOperation()

undoOperation()

redoOperation()

 

 

Demo: Edit sessions

 

  • GitHub 上の「demo_2_editor.py」のコードはこちら

Working with geometry

 

  • geomety オブジェクトを作成するのは少し面倒
  • 方法はいろいろある

 

  • geometry objects
cursor = arcpy.da.InsertCursor(fc, 'SHAPE@')
line = arcpy.Polyline(arcpy.Array([arcpy.Point( , ), arcpy.Point( , )]), arcpy.SpatialReference(3857))
cursor.insertRow([line])

 

  • esri json
cusor = arcpy.da.InsertCursor(fc, 'SHAPE@JSON')
json_line = {"paths": [[[ , ], [ , ]]], "spatialreference":{"wkid": 102100, "latestWkid":3857}}
cursor.insertRow([json.dumps(json_line)])

 

  • list of coordinates
cursor = arcpy.da.InsertCursor(fc, 'SHAPE@')
coordinate_list = [( , ), ( , )]
cursor.insertRow([coordinate_list])

 

 

Iterating over data

 

  • 多くのプロセスでは、データのカタログ化または反復処理が必要
  • 一般的なものは arcpy list functions
30+ across arcpy and modules
arcpy.da list functions:
ListDomains

ListFieldConflictFilters

ListReplicas

ListSubtypes

ListVersions

 

 

Walk

 

  • ディレクトリ構造をたどってArcGIS のデータタイプを返す
  • 3つのタプルを返す: path, path names, and filenames
walk = arcpy.da.Walk(workspace, datatype=datatypes)

for path, path_names, data_names in walk:
    for data_name in data_names:
        do_something()

 

 

Demo:Iterating over data

 

  • GitHub 上の「demo_3_list.py」のコードはこちら

 

Numpy

 

  • Numpy は科学計算用のサード パーティ製 Pythonライブラリ
    • 強力な配列オブジェクト
    • 洗練された分析機能
  • arcpy.daは、テーブルやフィーチャクラスと numpy arrays への相互変換をサポート
    • FeatureClassToNumPyArray, TableToNumPyArray
  • raster と numpy.arrays も相互に変換可能
    • RasterToNumPyArray, NumPyArrayToRaster

NumPy functions

 

  • arcpy.da はその他にもテーブルやフィーチャクラスへの変換をサポート
FeuatureClassToNumPyArray

TableToNumPyArray

NumPyArrayToFeatureClass

NumPyArrayToTable

ExtendTable

 

 

Export to NumPy

 

  • さらに分析するために、テーブルやフィーチャ クラスから numpy arrays へ変換可能
import arcpy
import numpy
   
in_fc = "c:/data/usa.gdb/USA/counties"
field1 = "INCOME"
field2 = "EDUCATION"
   
array1 = arcpy.da.FeatureClassToNumPyArray(in_fc, [field1, field2])
   
# Print correlation coefficients for comparison of 2 fields
print numpy.corrcoef((array1[field1], array1[field2]))

 

 

Import from NumPy

 

  • numpy での成果を、エクスポートしてArcGIS に戻す

 

point:

array1 = numpy.array([(1, ( , )), (2, ( , ))], numpy.dtype([('idfield', numpy.int32), ('XY', '<f8', 2)]))
sr = arcpy.SpatialReference(wkid) 
arcpy.da.NumPyArrayToFeatureClass(array1, outFC, ['XY'], sr)

 

 

 

pandas

 

  • pandas は次のような特徴の3rd パーティライブラリ
    • ハイパフォーマンス
    • 使いやすいデータ構造と
    • 解析ツール
def features_to_pandas(in_features, fields):
    in_arr = arcpy.da.FeatureClassToNumPyArray(in_features, fields)
    return pandas,DataFrame(in_arr)

def pandas_to_features(dataframe, output, geometry_columns, wkid=None):
    in_arr = dataframe.to_records()
    spatial_ref = '' if not wkid else arcpy.SpatialReference(wkid)
    return arcpy.da.NumPyArrayToFeatureClass(in_arr, output, geometry_columns, spatial_reference=spatial_ref)

 

 

Demo: arcpy, numpy and pandas

 

  • GitHub 上の「demo_4_numpy.py」のコードはこちら

 

 

関連:

 

Attachments

    Outcomes