データの探索とフィーチャクラスの投影変換

プロジェクトを開いてデータセットを確認

Python を使用してジオプロセシング ツールを実行する前に、データセットをダウンロードして ArcGIS Pro のデータセットを確認します。

  1. このチュートリアルのデータ」をダウンロードして、お使いのコンピューター上の場所にコンテンツを展開します。

    .zip ファイルには [PythonWorkflow] というフォルダーがあります。

    このチュートリアルでは、C:\Lessons\PythonWorkflow\ に、データが表示されます。 別のフォルダーを使用することもできますが、使用する場合は以下の手順およびコードでそのパスを調整する必要があります。

  2. C:\Lessons\PythonWorkflow\ フォルダーで、[Workflow.aprx] をダブルクリックします。

    ArcGIS Pro でワークフロー プロジェクトが開きます。

  3. [カタログ] ウィンドウがまだ表示されていない場合は、[表示] タブで [カタログ ウィンドウ] をクリックします。

    カタログ ウィンドウ ボタン

  4. [カタログ] ウィンドウで、[フォルダー] を展開し、[PythonWorkflow] を展開します。
  5. [Transportation.gdb] を展開します。

    フィーチャクラスを表示する、展開した Transportation ジオデータベース

    このジオデータベースのフィーチャクラスは、交通に関連しています。 たとえば、これらのフィーチャクラスからネットワークを構築する必要があったとします。 そのためには、同じフィーチャ データセットに格納され、同じ座標系である必要があります。 現時点では、そうなっていません。

    このチュートリアルでは、Python コードを使用してフィーチャクラスの座標系をチェックし、[投影変換] ツールを使用して、まだ正しい座標系になっていないデータセットを変換し、新しいジオデータベースとフィーチャデータセットにコピーします。 これにより、ネットワークを作成できますが、このチュートリアルではネットワークを構築しません。

    Python コードに取り組む前に、選択したデータセットの座標系を確認し、[投影変換] ツールを手動で実行します。 これにより、Python コードを使用してプロセスを自動化するために必要な情報を取得できます。

  6. [bike_racks] を右クリックし、[現在のマップに追加] をクリックします。

    現在のマップに追加オプション

  7. 同じ方法を使用して、[roads] フィーチャクラスをマップに追加します。

    これらのフィーチャクラスは、ワシントン D.C. 内の駐輪ラックと道路を表しています。

    次に、2 つのフィーチャクラスの座標系を確認します。

  8. [コンテンツ] ウィンドウで、[マップ] を右クリックし、[プロパティ] をクリックします。

    マップ プロパティ オプション

  9. [マップ プロパティ: マップ] ウィンドウで、[座標系] をクリックします。

    座標系タブ

  10. [レイヤー] を展開し、[WGS 1984] 座標系と [NAD 1983 StatePlane Maryland FIPS 1900 (US Feet)] 座標系のエントリを展開します。

    2 つの座標系のエントリを展開します。

    bike_racks フィーチャクラスには WGS 1984 という地理座標系が使用され、道路と境界フィーチャクラスには NAD 1983 StatePlane Maryland FIPS 1900 (US Feet) というメリーランド州の State Plane Coordinate System が使用されています。

    今回の目的は、すべてのフィーチャクラスを投影座標系でデータセットに格納することです。

  11. [OK] をクリックして、[マップ プロパティ] ウィンドウを閉じます。

    ジオデータベースを調査し、フィーチャクラスが使用する 2 つの座標系を特定しました。 次に、1 つのフィーチャクラスを投影変換します。

フィーチャクラスの投影変換

次に、1 つのフィーチャクラスを投影変換して、そのツールに必要なパラメーターを調べます。

  1. リボンの [解析] をクリックし、[ジオプロセシング] セクションで、[ツール] をクリックします。

    解析をクリックして、ジオプロセシング セクションで、ツールをクリックします。

    [ジオプロセシング] ウィンドウが表示されます。

  2. [ジオプロセシング] ウィンドウの検索ボックス内をクリックし、「project」と入力します。
  3. 検索結果で、[投影変換 (データ管理ツール)] をクリックします。
  4. [投影変換] ツール ウィンドウの [入力データセット、またはフィーチャクラス] パラメーターで、[bike_racks] を選択します。
  5. [出力データセット、またはフィーチャクラス] の名前で、参照ボタンをクリックし、[Transportation] ジオデータベースを参照します。 ジオデータベースを展開し、[名前] ボックスに「bike_racks_sp」と入力します。 [OK] をクリックします。
  6. [出力座標系] で、ドロップダウン リストをクリックし、[roads] をクリックします。

    パラメーターが設定された投影変換ツール。

    [roads] を選択すると、[出力座標系] の値が roads フィーチャクラスの座標系である State Plane Maryland 座標系に設定されます。

    入力と出力の地理座標系が異なるため、[地理座標系変換] パラメーターは [WGS_1984_(ITRF00) To_NAD_1983] に設定されます。

    注意:

    入力フィーチャクラスと出力フィーチャクラスの地理座標系が異なる場合、地理座標系変換が必要です。 地理座標系が同一の場合、このパラメーターに値のリストが表示されません。 変換が必要な場合は、入力と出力の地理座標系に基づいてドロップダウン リストが表示され、デフォルトの変換が選択されます。 このチュートリアルでは、このデフォルトの座標変換を使用します。

  7. [実行] をクリックします。

    [投影変換] ツールが実行され、投影変換されたフィーチャクラスがアクティブなマップに追加されます。

    ネットワークで使用するデータを準備するには、ジオデータベース内のすべてのフィーチャクラスに対して、座標系をチェックし、[投影変換] ツールを実行する必要があるかどうかを判断するプロセスを繰り返す必要があります。 投影変換する必要があるフィーチャクラスを投影変換します。 その他のフィーチャクラスは投影変換せずにコピーします。

    これらのステップを手動で繰り返す代わりに、Python コードを使用してプロセスを自動化します。

  8. [投影変換] ツールを閉じます。
  9. [カタログ] ウィンドウで、[bike_racks_sp] フィーチャクラスを右クリックして、[削除] をクリックし、[はい] をクリックしてフィーチャクラスを完全に削除します。

    これで、Python コードを使用してワークフローを開始する準備ができました。

コードを使用してフィーチャクラスを条件付きでコピーする

次に、以前にコメントアウトしたコードの一部を使用して、Transportation.gdb ジオデータベース内のフィーチャクラスを表示します。 各フィーチャクラスの空間参照 WKID が 2248 であるかどうかをチェックするロジックを追加し、その条件が true の場合にフィーチャクラスを新しいジオデータベースにコピーするコードを追加します。

  1. IDLE で、以前にコメントアウトしたコード行を選択します。
  2. [Format] をクリックし、[Uncomment Region] をクリックします。

    コードのコメントを解除します。

    コードのコメントを解除すると、各行の前のハッシュ記号が削除されるため、コードはコメントとして解釈されずに実行されます。

    コメントを解除したコードにより、現在のワークスペースのフィーチャクラスのリストが作成され、リスト内の各アイテムの説明を使用して空間参照が抽出されます。 ここで、その情報を出力する代わりに、空間参照値をチェックし、フィーチャクラスをコピーまたは投影変換するコードを追加します。

    [フィーチャのコピー] ツールと [投影変換] ツールは、両方とも入力フィーチャクラスを受け取り、出力フィーチャクラスを生成します。 新しいフィーチャクラスは新しいジオデータベース内に存在するため、フィーチャクラスの名前は同じままにできますが、出力のパスは異なります。

    入力フィーチャクラスは、変数 fc で表されます。 fc の値は、現在のワークスペース内のフィーチャクラスのリストから取得されたフィーチャクラス名です。

    たとえば、ある入力フィーチャクラスの絶対パスが C:\Lessons\PythonWorkflow\Transportation.gdb\roads だとします。

    ワークスペースが設定されているため、ツールで roads などのフィーチャクラス名を直接使用できます。 現在のワークスペース内のフィーチャクラスを操作する場合、絶対パスは不要です。 このため、desc = arcpy.da.Describe(fc)desc = arcpy.da.Describe("roads") は正常に動作します。

    ただし、新しいワークスペース内の新しいフィーチャクラスの出力フィーチャクラス パラメーターには、絶対パスを指定する必要があります。 このパスは、以前にスクリプトで環境を設定したときと同様、os.path.join() を使用して構築することができます。

  3. print(f"{fc}: で始まるコード行を選択し、次のコード行に置き換えます。

    new_fc = os.path.join(mypath, new_gdb, fds, fc)

    この行は、for fc in fcs: ループ コード ブロックの内側で、同じインデント レベルに配置する必要があります。

    この行で、新しい変数 new_fc が、データが存在するフォルダー (mypath)、新しいジオデータベース (new_gdb)、および新しいフィーチャ データセット (fds) を結合して作成したパスと等しくなるように設定されます。 パスの末尾には、入力フィーチャクラス (変数 fc の値) と同様に、新しいフィーチャクラスの名前が設定されます。 パスのこの部分は、フィーチャクラスのリストに対するループが繰り返されるたびに変化します。

    出力フィーチャクラスの絶対パスが作成されたため、座標系に基づいて各フィーチャクラスをコピーするか投影変換するかを判断するコードを追加する準備が整いました。 Python で、if ステートメントを使用してさまざまな条件をテストし、ステートメント内の条件が true かどうかに応じて異なるコード ブロックを実行させることができます。

  4. new_fc = os.path.join 行の後に、同じインデント レベルで (for ループの内側)、次のコード行を追加します。

    if sr.factoryCode == 2248:

    このコードは、sr オブジェクトに factoryCode 値として格納されているフィーチャクラスの WKID が、State Plane Maryland 座標系の WKID である 2248 と一致するかどうかをチェックします。

    このコードは if ステートメントと条件式を使用し、ステートメントが true の場合に実行されるコード ブロックが続くことを示すため、コロンで終わっています。

    ステートメントは二重等号を使用しています。 Python で、単一等号は変数に値を設定するために使用され、二重等号は等価かどうかをチェックするために使用されます。

  5. このコード行の末尾をクリックして Enter キーを押します。

    この結果、次のコード行に正しいインデントが設定され、if ステートメント行に対して 4 つのスペースでインデントされます。 これは、sr.factoryCode が値 2248 と等しい場合にのみ実行される新しいコード ブロックの開始点です。

    出力フィーチャクラスの絶対パスが作成され、座標系のテストが正常に完了したため、フィーチャクラスをコピーするコードを追加できます。

  6. 新しくインデントされた行に、次のコード行を追加します。

    arcpy.CopyFeatures_management(fc, new_fc)
            print(f"The feature class {fc} has been copied.")

    最初の行は、フィーチャのコピー ツールを実行して、現在のフィーチャクラスを新しいジオデータベースにコピーします。

    2 行目は、新しいデータセットが作成されたことを示す、書式設定された文字列を出力します。

    次に、完全なコードを示します。

    import arcpy
    import os
    mypath = "C:/Lessons/PythonWorkflow"
    gdb = "Transportation.gdb"
    new_gdb = "Metro_Transport.gdb"
    fds = "Metro_Network"
    arcpy.env.workspace = os.path.join(mypath, gdb)
    arcpy.env.overwriteOutput = True
    new_gdb_path = arcpy.CreateFileGDB_management(mypath, new_gdb)
    print(f"The geodatabase {new_gdb} has been created.")
    arcpy.CreateFeatureDataset_management(new_gdb_path, fds, 2248)
    print(f"The feature dataset {fds} has been created.")
    fcs = arcpy.ListFeatureClasses()
    for fc in fcs:
        desc = arcpy.da.Describe(fc)
        sr = desc["spatialReference"]
        new_fc = os.path.join(mypath, new_gdb, fds, fc)
        if sr.factoryCode == 2248:
            arcpy.CopyFeatures_management(fc, new_fc)
            print(f"The feature class {fc} has been copied.")

    WKID が 2248 の場合にジオデータベース間でフィーチャクラスをコピーするロジックがスクリプトに追加されています。

  7. コードを保存して実行します。

    一致するフィーチャクラスがコピーされます。

    コードが実行されます。 これにより、ジオデータベースとフィーチャデータセットが作成され、State Plane Maryland 座標系を使用していた 5 つのレイヤーがコピーされます。

  8. ArcGIS Pro[カタログ] ウィンドウで、[PythonWorkflow] フォルダーを更新します。
  9. [Metro_Transport] ジオデータベースを更新して展開します。
  10. [Metro_Network] フィーチャ データセットを更新して展開します。

    5 つのフィーチャクラスが新しいジオデータベースにコピーされます。

    ジオデータベースとデータセットには、データセットの座標系と一致するフィーチャクラスが含まれます。

データを探索したので、Python を使用してフィーチャクラスのリストを作成し、記述します。


フィーチャクラスのリスト作成と記述

ジオデータベースのデータにアクセスし、データ管理や解析操作を行うことがよくあります。 あなたは、使用可能なものを確認し、データについて知りたいと考えています。 たとえば、ジオデータベースのポイント フィーチャクラスの処理のみを行いたい場合は、まずそれらのリストを入手してからツールに入力することになります。 Python は、こうした作業を行う際に便利です。 Python では、はじめにジオデータベースにあるフィーチャクラスのリストを作成し、空間参照を記述するためのコードを記述します。

Python を使用してフィーチャクラスを説明する

このワークフローでは、まずフィーチャクラスの座標系を調べます。 これを行うには、[Python] ウィンドウで Python コードを使用します。

  1. リボンの [解析] をクリックし、[ジオプロセシング] セクションで、[Python] ボタンのドロップダウン矢印をクリックして [Python ウィンドウ] をクリックします。

    Python ウィンドウ オプション

  2. [Python] ウィンドウの下部にあるプロンプト セクションをクリックし、次のコードを入力して Enter キーを押します。

    desc = arcpy.da.Describe("bike_racks")

    bike_racks フィーチャクラスを説明するコード

    Enter キーを押すと、コードがすぐに実行されます。 実行しても何も出力されませんが、変数 desc が作成され、[Describe] 関数を bike_racks フィーチャクラスに対して実行した結果と等しくなるように変数が設定されます。

    [Describe] 関数は、データセットのプロパティを含む辞書を返します。 これにより、空間参照などのプロパティにアクセスできます。

  3. プロンプト セクションで、次のコードを追加し、Enter キーを押します。

    sr = desc["spatialReference"]

    これにより、新しい変数 sr に、データセット プロパティの辞書の SpatialReference キーに格納されている値が設定されます。 SpatialReference オブジェクトには、データセットの座標系に関するすべての関連情報が含まれています。 これにより、特定のプロパティを確認することができます。

  4. プロンプト セクションで、次のコードを追加し、Enter キーを押します。

    print(sr.name)

    これにより、空間参照オブジェクトの名前が出力されます。

    空間参照名を出力

    このように各フィーチャクラスの座標系を順番にチェックするのは少し面倒な作業であるため、リスト関数でリストを作成してから、すべてのフィーチャクラスを処理します。

フィーチャクラスのリストを作成して説明する

フィーチャクラスのリストを作成し、Python のループ構造を使用してリストを処理し、それぞれのフィーチャクラスを説明することで、フィーチャクラスの座標系をチェックする処理を高速化できます。

  1. プロンプト セクションで、次のコードを追加し、Enter キーを押します。

    fcs = arcpy.ListFeatureClasses()

    これにより、変数 fcs が作成され、ListFeatureClasses 関数を現在のワークスペースに対して実行した結果と等しくなるように変数が設定されます。 これまでにワークスペースを明示的に設定していませんが、[Transportation.gdb] がこのプロジェクトのデフォルトのワークスペースです。 この関数は、[Transportation.gdb] 内のフィーチャクラスのリストを返します。

  2. プロンプト セクションで、次のコードを追加し、Enter キーを押します。

    print(fcs)

    その結果、フィーチャクラス名の Python リストが出力されます。 リストは角括弧で囲まれ、フィーチャクラス名はカンマで区切られた Python 文字列です。

    ['bus_lines', 'boundary', 'street_lights', 'roads', 'traffic_analysis_zones', 'bike_routes', 'bike_racks', 'parking_zones', 'intersections', 'station_entrances']

    次に、for ループを使用して、リストの各アイテムを処理します。

  3. プロンプト セクションで、次のコードを追加します。

    for fc in fcs:
        desc = arcpy.da.Describe(fc)
        sr = desc["spatialReference"]
        print(f"{fc}: {sr.name}")

    フィーチャクラスのリストを処理する for ループ

    最初の行は for ループを定義しています。 一時変数 fc が作成され、fcs リスト内の各フィーチャクラスの名前が割り当てられます。 この行はコロンで終わっており、リスト内の各アイテムに対して実行されるコード ブロックが続くことを示しています。 次の 3 つの行は、コード ブロックの一部であることを示すため、4 つのスペースでインデントされています。 コード ブロックの最初の行は変数 desc を作成し、Describe 関数を fc 変数に格納されている現在のフィーチャクラス値に対して実行した結果と等しくなるようにその変数を設定します。 2 行目は sr 変数を作成し、desc に格納されている spatialReference オブジェクトにその変数を設定します。 3 行目は、フィーチャクラス名、コロン、および空間参照名を含む、書式設定された文字列を出力します。

    このブロック内のコードは、前に行った bike_racks フィーチャクラスの空間参照名を取得するプロセスを繰り返しますが、リスト内の各アイテムに設定された変数に対して実行するため、すべてのフィーチャクラスの結果を処理および報告します。

  4. Enter キーを 2 回押して、for ループとそのコード ブロックを実行します。

    リストされている各フィーチャクラスの空間参照

    フィーチャクラスの半分で 1 つの座標系が使用され、残り半分でもう 1 つの座標系が使用されています。

    次に、ジオデータベースを作成するコードを記述し、[投影変換] および [フィーチャのコピー] ツールを使用して、共通の投影座標系を持つ同じデータセットにフィーチャクラスを取り込みます。 これまでに行った作業をエクスポートし、スクリプトの基準として使用します。

スクリプトの作成

次に、引き続きこのプロセスを自動化するコードをスクリプトとして記述します。 [Python] ウィンドウでもコードをテストできますが、長いスクリプトの場合は通常 Python エディターで記述することをお勧めします。 ここまでのコードをエクスポートして、デフォルトの Python エディターである IDLE で作業を続けます。

  1. [Python] ウィンドウのトランスクリプト セクションで右クリックして、[トランスクリプトの保存] をクリックします。

    トランスクリプトの保存オプション

  2. [トランスクリプトの保存] ウィンドウで、データを抽出した [PythonWorkflow] フォルダーを参照し、トランスクリプトに「workflow_project.py」という名前を付け、[保存] をクリックします。

    これにより、トランスクリプトが Python スクリプト ファイルとして保存され、Python エディターで開くことができます。

  3. Microsoft File Explorer を起動し、[PythonWorkflow] フォルダーに移動します。
  4. workflow_project.py ファイルを右クリックして、[Edit with IDLE (ArcGIS Pro)] をクリックします。

    Edit with IDLE (ArcGIS Pro) オプション

    注意:
    ArcGIS Desktop 10.x (ArcMap) もインストールされている場合、ショートカット メニューに [Edit with IDLE] ショートカットも表示されます。 正しいバージョンの Python が起動されないため、このショートカットを使用しないでください。

    注意:
    [Edit with IDLE (ArcGIS Pro)] がショートカット メニューに表示されない場合は、[スタート] をクリックして [ArcGIS] を展開し、[Python コマンド プロンプト] をクリックします。 [Python コマンド プロンプト] ウィンドウに「idle」と入力して Enter キーを押します。 IDLE (Python 3.9 Shell) ウィンドウが表示されます。 [File] をクリックして [Open] をクリックします。 workflow_project.py ファイルを参照して開きます。

    スクリプトが Python のデフォルト エディターである IDLE で開きます。 スクリプトには、[Python] ウィンドウのトランスクリプト セクションのすべてのコードと、出力されたメッセージ (行頭がハッシュ文字のコメントとして表示される) が含まれます。

    IDLE Python エディター

  5. IDLE エディターウィンドウで、fcs = arcpy.ListFeatureClasses() 行より前のコードをすべて削除します。
  6. すべてのコメント行を削除します。
  7. print(fcs) 行を削除します。

    残ったコードは次のようになります。

    fcs = arcpy.ListFeatureClasses()
    for fc in fcs:
        desc = arcpy.da.Describe(fc)
        sr = desc["spatialReference"]
        print(f"{fc}: {sr.name}")

    次に、2 つのライブラリをインポートする行を追加し、いくつかの変数を設定して、ワークスペースを設定します。

  8. fcs = arcpy.ListFeatureClasses() 行の前に新しい行を追加し、スクリプトの先頭に次の行を追加します。

    import arcpy
    import os

    コードの最初の行は、ArcPy の機能を ArcGIS Pro の外部で実行する際にスクリプトで使用できるようにするため、ArcPy パッケージをインポートしています。 2 行目は、ファイル パスを処理する際に使用される os モジュールをインポートしています。

  9. 最初の 2 行の後に新しい行を追加し、次のコード行を追加します。
    mypath = "C:/Lessons/PythonWorkflow"
    gdb = "Transportation.gdb"
    arcpy.env.workspace = os.path.join(mypath, gdb)

    最初の行は、データの場所を指定します。 [PythonWorkflow] フォルダーを別の場所に抽出した場合、この行がコンピューター上のパスになるように編集する必要があります。 この値は、mypath という名前の変数に割り当てられます。 この変数は、ワークスペースの設定に使用されるほか、ファイル ジオデータベースの作成などの他のタスクにも使用されます。

    パスでは、単一のバックスラッシュ (\) ではなく、単一のスラッシュ (/) が使用されます。 Python では、単一のバックスラッシュは、エスケープ文字として使用されるため、予期しない結果が生じる可能性があります。 単一のスラッシュの代わりに、文字列 (例: r"C:\Lessons\PythonWorkflow") の前に文字 r (raw) を追加したり、2 つのバックスラッシュを使用したり (例: "C:\\Lessons\\PythonWorkflow") することもできます。 この 3 つは、いずれも正しい表記と見なされ、区別なく使用できます。

    次の行は、変数 gdb を、対象のフィーチャクラスが格納されているジオデータベースの名前と等しくなるように設定します。

    最後の行は、データが存在するフォルダー (mypath) とジオデータベースの名前 (gdb) を組み合わせてワークスペースを設定します。 os.path.join() 関数は、これらの 2 つの文字列を組み合わせて、ワークスペースのパスを新しい文字列に設定するために使用されます。 単一のバックスラッシュ (\) を使用することなく、堅牢なパス文字列が作成されるため、os.path.join() を使用してワークスペースを設定することをお勧めします。 Python ではエスケープ文字として読み取られ、エラーが発生することがあります。

    次に、これまでの完全なスクリプトを示します。

    import arcpy
    import os
    mypath = "C:/Lessons/PythonWorkflow"
    gdb = "Transportation.gdb"
    arcpy.env.workspace = os.path.join(mypath, gdb)
    fcs = arcpy.ListFeatureClasses()
    for fc in fcs:
        desc = arcpy.da.Describe(fc)
        sr = desc["spatialReference"]
        print(f"{fc}: {sr.name}")

    最初のテスト ポイントでのスクリプト

    これで、スクリプトをテストして、動作を確認できるようになりました。

  10. [File] をクリックして、[Save] をクリックします。

    これにより、スクリプトに加えた変更が保存されます。 IDLE でキーボード ショートカット Ctrl+S キーを使用して、プロジェクトを保存することもできます。

  11. [Run] をクリックし、[Run Module] をクリックします。

    Run Module オプション

    これでスクリプトが実行されます。 キーボード ショートカット F5 キーを使用して、スクリプトを実行することもできます。

    最初のテストの結果

    IDLE Shell ウィンドウが表示され、ArcPy モジュールがインポートされる短い時間の後、フィーチャクラス名と空間参照名が出力されます。

フィーチャクラスのリストを作成し、記述するための Python コードを記述しました。 このワークフローを自動化するスクリプトを完成させるには、次の機能を追加します。1) ジオデータベースの作成、2) フィーチャ データセットの作成、3) すでに投影変換されているフィーチャクラスのコピー、4) 地理座標系を使用しているフィーチャクラスの投影変換 各エレメントのコードを記述し、コードをテストしてから、次のエレメントに進みます。


ジオデータベース スキーマの作成

Python の知識が少し身についたところで、これを使用してジオデータベースやフィーチャ データセットなどのジオデータベース スキーマを作成していきます。 スキーマの作成後は、フィーチャクラスをジオプロセシング ワークフローとしてスキーマにコピーします。

コードを使用してジオデータベースを作成する

次に、ジオデータベースを作成するコードをスクリプトに追加します。 スクリプトを複数回テストする必要があるため、以前に作成したデータを上書きできるようにする必要があります。 このためには、スクリプトに環境設定を追加します。

  1. arcpy.env.workspace で始まる行の後に、行を追加して、次のコードを追加します。

    arcpy.env.overwriteOutput = True

    次に、新しいジオデータベースと新しいフィーチャ データセットの名前を格納する変数を作成します。

  2. gdb = "Transportation.gdb" 行の後に、行を追加して、次のコードを追加します。

    new_gdb = "Metro_Transport.gdb"
    fds = "Metro_Network"

    変数を使用することで、残りのスクリプトで名前を繰り返し記述しなくて済みます。 これにより、コードを再利用しやすくなります。 ジオデータベースまたはデータセットに別の名前を使用する場合、スクリプトの 1 カ所を変更するだけで済みます。

    次に、ジオデータベースを作成するコードを追加します。

  3. arcpy.env.overwriteOutput で始まる行の後に、次のコードを追加します。

    new_gdb_path = arcpy.CreateFileGDB_management(mypath, new_gdb)

    この行は、ファイル ジオデータベースの作成ツールを呼び出しています。 括弧内で、最初の必須パラメーターである新しいジオデータベースの場所が、設定したパス値を含む変数 mypath に設定されるように指定します。 カンマの後に、ツールの他の必須パラメーターであるファイル ジオデータベース名を指定します。 変数 new_gdb には新しいジオデータベースの名前が含まれています。

    また、この行はジオデータベースを作成した結果を変数に割り当てています。 変数 new_gdb_path には、新規に作成されたジオデータベースのパスと名前が含まれています。 これにより、スクリプト内でこの新しいジオデータベースを参照しやすくなります。

    スクリプトをテストする前に、テストする必要のないコードをコメントアウトします。

  4. new_gdb_path 行より後のコード行をすべて選択します。

    選択したコード行

  5. [Format] をクリックし、[Comment Out Region] をクリックします。

    Comment Out Region オプション

    これにより、選択したコードの各行の先頭に 2 つのハッシュ文字が追加されます。 Python は、ハッシュ記号で始まる行をコメントとして解釈するため、これらの行は実行されません。 これらの行を削除することもできますが、一部のコードは再度使用されます。 これらの行をコメント アウトすることで、後で使用するためにスクリプトにコードを残しつつ、コード自体は実行されないようにすることができます。

    コメント ブロック

    次に、これまでのコードを示します。

    import arcpy
    import os
    mypath = "C:/Lessons/PythonWorkflow"
    gdb = "Transportation.gdb"
    new_gdb = "Metro_Transport.gdb"
    fds = "Metro_Network"
    arcpy.env.workspace = os.path.join(mypath, gdb)
    arcpy.env.overwriteOutput = True
    new_gdb_path = arcpy.CreateFileGDB_management(mypath, new_gdb)
    ##fcs = arcpy.ListFeatureClasses()
    ##for fc in fcs:
    ##    desc = arcpy.da.Describe(fc)
    ##    sr = desc["spatialReference"]
    ##    print(f"{fc}: {sr.name}")

  6. スクリプトを保存して実行します。

    IDLE Shell ウィンドウが再起動し、しばらくすると入力プロンプト >>> が返されます。 現在、コードにはシェルに情報を出力する行が存在しないため、コードが動作したかどうかを判断することは困難です。 ArcGIS Pro でチェックします。

  7. ArcGIS Pro[カタログ] ウィンドウの [フォルダー] セクションで、[PythonWorkflow] フォルダーを右クリックし、[更新] をクリックします。

    更新オプション

  8. [PythonWorkflow] フォルダーを展開します。

    追加された Metro_Transport.gdb

    新しいジオデータベースがフォルダー内にあります。 現時点では空白です。 ジオデータベースを削除しますが、まずは IDLE ウィンドウを閉じる必要があります。

  9. [IDLE Shell] ウィンドウを閉じます。
  10. [カタログ] ウィンドウで [Metro_Transport.gdb] を右クリックして、[削除] をクリックし、[はい] をクリックしてジオデータベースを完全に削除します。

    スクリプトをテストしている間、出力を削除すると、スクリプトが動作しているかどうかを確認しやすくなるため便利です。

    スクリプトが動作していることを示すもう 1 つの指標は、実行されている内容を示すメッセージを追加することです。 コードに print ステートメントを追加すると、実行されている内容を追跡しやすくなります。

  11. IDLE エディター ウィンドウで、new_gdb_path = arcpy.CreateFileGDB で始まる行の後に、新しい行を追加して、次のコードを追加します。

    print(f"The geodatabase {new_gdb} has been created.")

    追加された print コード行

    この print ステートメントは、new_gdb 変数の値を含む、書式設定された文字列を出力します。 print ステートメントはスクリプトの実行には必要ありませんが、スクリプトの実行内容を追跡しやすくなります。 また、長いスクリプトでのエラーのデバッグに非常に役立ちます。 スクリプト内のステータスを示す複数の print ステートメントをさまざまなポイントに追加することで、各メッセージが表示された際に、スクリプトがそのポイントまで進んでいることを確認できます。 書式設定された文字列を使用して、スクリプト内の変数の値を出力することもできます。これは、エラーのデバッグに非常に役立ちます。

  12. スクリプトを保存します。

コードを使用してフィーチャ データセットを作成する

次に、新しいジオデータベースにフィーチャ データセットを作成します。 フィーチャ データセットの定義の 1 つは、フィーチャ データセット内のすべてのフィーチャクラスが同じ座標系を共有することです。

このデータセットには、State Plane Maryland 座標系を使用します。 Python で座標系を設定する際に座標系の名前を使用することもできますが、WKID (well-known identifier) と呼ばれる短いコードを使用するほうが簡単です。

  1. ArcGIS Pro[コンテンツ] ウィンドウで、[roads] レイヤーを右クリックし、[プロパティ] をクリックします。
  2. [レイヤー プロパティ] ウィンドウで、[ソース] タブをクリックします。

    ソース タブ

  3. [データ ソース] をクリックし、[データ ソース] セクションを折りたたみます。

    データ ソース セクション

  4. [空間参照] をクリックして展開します。

    空間参照セクション

    この座標系の WKID コードは 2248 です。

    WKID コード 2248

  5. [キャンセル] をクリックして、[レイヤー プロパティ] ウィンドウを閉じます。

    ここで、この WKID コードを使用して、フィーチャ データセットの空間参照を設定します。

  6. IDLE で、print(f"The geodatabase で始まる行の後に、次のコード行を追加します。

    arcpy.CreateFeatureDataset_management(new_gdb_path, fds, 2248)
    print(f"The feature dataset {fds} has been created.")

    フィーチャ データセットを作成してレポートを出力するコード

    最初の行は、[フィーチャ データセットの作成] ツールに 3 つの必須パラメーターを指定して実行しています。 最初のパラメーターは、フィーチャ データセットを作成するジオデータベースの場所、2 つ目はフィーチャ データセットの名前、3 つ目はデータセットの座標系の WKID です。 new_gdb_path 変数には、データベースへの絶対パスが含まれています。 fds 変数には、あらかじめフィーチャ データセットの名前が割り当てられています。

    座標系を設定する別の方法として、既存のフィーチャクラスへのパスを指定する方法があります。たとえば、Transportation.gdb ジオデータベース内の roads フィーチャクラスへのパスを指定します。

    2 行目は、新しいデータセットが作成されたことを示す、書式設定された文字列を出力します。

    次に、完全なコードを示します。

    import arcpy
    import os
    mypath = "C:/Lessons/PythonWorkflow"
    gdb = "Transportation.gdb"
    new_gdb = "Metro_Transport.gdb"
    fds = "Metro_Network"
    arcpy.env.workspace = os.path.join(mypath, gdb)
    arcpy.env.overwriteOutput = True
    new_gdb_path = arcpy.CreateFileGDB_management(mypath, new_gdb)
    print(f"The geodatabase {new_gdb} has been created.")
    arcpy.CreateFeatureDataset_management(new_gdb_path, fds, 2248)
    print(f"The feature dataset {fds} has been created.")
    ##fcs = arcpy.ListFeatureClasses()
    ##for fc in fcs:
    ##    desc = arcpy.da.Describe(fc)
    ##    sr = desc["spatialReference"]
    ##    print(f"{fc}: {sr.name}")

  7. コードを保存して実行します。

    コードが実行され、しばらくすると、2 つのステータス メッセージが IDLE シェルに出力されます。

    コード実行後に出力されたメッセージ

  8. ArcGIS Pro[カタログ] ウィンドウで、[PythonWorkflow] フォルダーを右クリックし、[更新] をクリックします。

    [Metro_Transport] ジオデータベースが作成されました。

  9. [Metro_Transport] ジオデータベースを展開します。

    Metro_Network フィーチャ データセット

    [Metro_Network] フィーチャ データセットが作成されました。

  10. [IDLE Shell] ウィンドウを閉じ、[Metro_Transport] ジオデータベースを削除します。

コードを使用してフィーチャクラスを条件付きでコピーする

次に、以前にコメントアウトしたコードの一部を使用して、Transportation.gdb ジオデータベース内のフィーチャクラスを表示します。 各フィーチャクラスの空間参照 WKID が 2248 であるかどうかをチェックするロジックを追加し、その条件が true の場合にフィーチャクラスを新しいジオデータベースにコピーするコードを追加します。

  1. IDLE で、以前にコメントアウトしたコード行を選択します。
  2. [Format] をクリックし、[Uncomment Region] をクリックします。

    Uncomment Region オプション

    コードのコメントを解除すると、各行の前のハッシュ記号が削除されるため、コードはコメントとして解釈されずに実行されます。

    コメントを解除したコードにより、現在のワークスペースのフィーチャクラスのリストが作成され、リスト内の各アイテムの説明を使用して空間参照が抽出されます。 ここで、その情報を出力する代わりに、空間参照値をチェックし、フィーチャクラスをコピーまたは投影変換するコードを追加します。

    [フィーチャのコピー] ツールと [投影変換] ツールは、両方とも入力フィーチャクラスを受け取り、出力フィーチャクラスを生成します。 新しいフィーチャクラスは新しいジオデータベース内に存在するため、フィーチャクラスの名前は同じままにできますが、出力のパスは異なります。

    入力フィーチャクラスは、変数 fc で表されます。 fc の値は、現在のワークスペース内のフィーチャクラスのリストから取得されたフィーチャクラス名です。

    たとえば、ある入力フィーチャクラスの絶対パスが C:\Lessons\PythonWorkflow\Transportation.gdb\roads だとします。

    ワークスペースが設定されているため、ツールで roads などのフィーチャクラス名を直接使用できます。 現在のワークスペース内のフィーチャクラスを操作する場合、絶対パスは不要です。 このため、desc = arcpy.da.Describe(fc)desc = arcpy.da.Describe("roads") は正常に動作します。

    ただし、新しいワークスペース内の新しいフィーチャクラスの出力フィーチャクラス パラメーターには、絶対パスを指定する必要があります。 このパスは、以前にスクリプトで環境を設定したときと同様、os.path.join() を使用して構築することができます。

  3. print(f"{fc}: で始まるコード行を選択し、次のコード行に置き換えます。

    new_fc = os.path.join(mypath, new_gdb, fds, fc)

    この行は、for fc in fcs: ループ コード ブロックの内側で、同じインデント レベルに配置する必要があります。

    この行で、新しい変数 new_fc が、データが存在するフォルダー (mypath)、新しいジオデータベース (new_gdb)、および新しいフィーチャ データセット (fds) を結合して作成したパスと等しくなるように設定されます。 パスの末尾には、入力フィーチャクラス (変数 fc の値) と同様に、新しいフィーチャクラスの名前が設定されます。 パスのこの部分は、フィーチャクラスのリストに対するループが繰り返されるたびに変化します。

    出力フィーチャクラスの絶対パスが作成されたため、座標系に基づいて各フィーチャクラスをコピーするか投影変換するかを判断するコードを追加する準備が整いました。 Python で、if ステートメントを使用してさまざまな条件をテストし、ステートメント内の条件が true かどうかに応じて異なるコード ブロックを実行させることができます。

  4. new_fc = os.path.join 行の後に、同じインデント レベルで (for ループの内側)、次のコード行を追加します。

    if sr.factoryCode == 2248:

    このコードは、sr オブジェクトに factoryCode 値として格納されているフィーチャクラスの WKID が、State Plane Maryland 座標系の WKID である 2248 と一致するかどうかをチェックします。

    このコードは if ステートメントと条件式を使用し、ステートメントが true の場合に実行されるコード ブロックが続くことを示すため、コロンで終わっています。

    ステートメントは二重等号を使用しています。 Python で、単一等号は変数に値を設定するために使用され、二重等号は等価かどうかをチェックするために使用されます。

  5. このコード行の末尾をクリックして Enter キーを押します。

    この結果、次のコード行に正しいインデントが設定され、if ステートメント行に対して 4 つのスペースでインデントされます。 これは、sr.factoryCode が値 2248 と等しい場合にのみ実行される新しいコード ブロックの開始点です。

    出力フィーチャクラスの絶対パスが作成され、座標系のテストが正常に完了したため、フィーチャクラスをコピーするコードを追加できます。

  6. 新しくインデントされた行に、次のコード行を追加します。

    arcpy.CopyFeatures_management(fc, new_fc)
            print(f"The feature class {fc} has been copied.")

    最初の行は、フィーチャのコピー ツールを実行して、現在のフィーチャクラスを新しいジオデータベースにコピーします。

    2 行目は、新しいデータセットが作成されたことを示す、書式設定された文字列を出力します。

    次に、完全なコードを示します。

    import arcpy
    import os
    mypath = "C:/Lessons/PythonWorkflow"
    gdb = "Transportation.gdb"
    new_gdb = "Metro_Transport.gdb"
    fds = "Metro_Network"
    arcpy.env.workspace = os.path.join(mypath, gdb)
    arcpy.env.overwriteOutput = True
    new_gdb_path = arcpy.CreateFileGDB_management(mypath, new_gdb)
    print(f"The geodatabase {new_gdb} has been created.")
    arcpy.CreateFeatureDataset_management(new_gdb_path, fds, 2248)
    print(f"The feature dataset {fds} has been created.")
    fcs = arcpy.ListFeatureClasses()
    for fc in fcs:
        desc = arcpy.da.Describe(fc)
        sr = desc["spatialReference"]
        new_fc = os.path.join(mypath, new_gdb, fds, fc)
        if sr.factoryCode == 2248:
            arcpy.CopyFeatures_management(fc, new_fc)
            print(f"The feature class {fc} has been copied.")

    for ループと if ステートメント

  7. コードを保存して実行します。

    一致するフィーチャクラスがコピーされます。

    コードが実行されます。 これにより、ジオデータベースとフィーチャデータセットが作成され、State Plane Maryland 座標系を使用していた 5 つのレイヤーがコピーされます。

  8. ArcGIS Pro[カタログ] ウィンドウで、[PythonWorkflow] フォルダーを更新します。
  9. [Metro_Transport] ジオデータベースを更新して展開します。
  10. [Metro_Network] フィーチャ データセットを更新して展開します。

    5 つのフィーチャクラスが新しいジオデータベースにコピーされます。

    ジオデータベースとデータセットには、データセットの座標系と一致するフィーチャクラスが含まれます。

コードを追加してフィーチャクラスを条件付きで投影変換する

このスクリプトを完成させる最後のステップとして、[投影変換] ツールを使用して State Plane Maryland 座標系を使用していないフィーチャクラスを投影変換し、その結果を新しいジオデータベース内のフィーチャデータセットに書き込むロジックを追加します。

  1. IDLE で、print(f"The feature class で始まるコード行の末尾をクリックし、Enter キーを押します。
  2. Backspace キーを押して、インデント レベルを 1 つ減らします。

    else ステートメントを追加しますが、このステートメントは前の if ステートメントと同じインデント レベルにする必要があります。

    else ステートメントは、if ステートメントが false の際に別のコード ブロックを実行する場合に使用されます。

  3. インデントを減らした新しい行に、次のコード行を追加します。

    else:
            arcpy.Project_management(fc, new_fc, 2248)
            print(f"The feature class {fc} has been projected.")

    if ステートメントと else ステートメントは同じインデント レベルです。

    else ステートメントは、if ステートメントで true でないことをチェックした後に実行するコード ブロックを含む論理分岐を作成します。 このロジックでは、WKID が 2248 の場合はフィーチャクラスをコピーし、2248 以外の場合はフィーチャクラスを投影変換します。

    次の行のうち 2 行目は、else 条件で実行されるコード ブロックの一部であるため、4 つのスペースでインデントされています。 [投影変換] ツールは、入力フィーチャクラスを State Plane Maryland 座標系に投影変換し、出力フィーチャクラスは新しいジオデータベースに格納されます。 [投影変換] ツールのパラメーターは、入力フィーチャクラス、出力フィーチャクラス、および出力座標系 (このパラメーターには WKID 2248 が使用されます) です。

    注意:
    [投影変換] ツールの 4 つ目のパラメーターは、オプションの変換です。 以前 [投影変換] ツールを実行した際に、NAD 1983 地理座標系と WGS 1984 地理座標系の間で変換が必要なことを確認しましたが、デフォルトではツールの実行時に適切な変換が選択されます。 このため、このコードで変換を指定する必要はありません。

    以前のすべてのフィーチャクラスの座標系をチェックした結果に基づくと、State Plane Maryland 座標系を使用していないフィーチャクラスが、ある特定の地理座標系を使用していることがわかります。 ただし、この特定の座標系を指定する必要はありません。 else ステートメントを使用することで、[投影変換] ツールは、特定の座標系に関係なく、if ステートメントが false のすべてのフィーチャクラスに対して実行されます。

    次に、完全なコードを示します。

    import arcpy
    import os
    mypath = "C:/Lessons/PythonWorkflow"
    gdb = "Transportation.gdb"
    new_gdb = "Metro_Transport.gdb"
    fds = "Metro_Network"
    arcpy.env.workspace = os.path.join(mypath, gdb)
    arcpy.env.overwriteOutput = True
    new_gdb_path = arcpy.CreateFileGDB_management(mypath, new_gdb)
    print(f"The geodatabase {new_gdb} has been created.")
    arcpy.CreateFeatureDataset_management(new_gdb_path, fds, 2248)
    print(f"The feature dataset {fds} has been created.")
    fcs = arcpy.ListFeatureClasses()
    for fc in fcs:
        desc = arcpy.da.Describe(fc)
        sr = desc["spatialReference"]
        new_fc = os.path.join(mypath, new_gdb, fds, fc)
        if sr.factoryCode == 2248:
            arcpy.CopyFeatures_management(fc, new_fc)
            print(f"The feature class {fc} has been copied.")
        else:
            arcpy.Project_management(fc, new_fc, 2248)
            print(f"The feature class {fc} has been projected.")

    スクリプトの完全なコード

  4. スクリプトを保存して実行します。

    コードが実行されます。 これにより、ジオデータベースとフィーチャ データセットが作成され、State Plane Maryland 座標系を使用していた 5 つのレイヤーがコピーされ、WGS84 座標系を使用していた 5 つのレイヤーが投影変換されます。

    最終的なコードの実行結果

  5. ArcGIS Pro[カタログ] ウィンドウで、[Metro_Network] フィーチャ データセットを更新します。

    データセットには、すべてのフィーチャクラスが、すべて正しい座標系で含まれています。

    すべてのフィーチャクラスを含む最終的なジオデータベース

    コードは正常に動作しており、この時点で、ジオメトリック ネットワークを作成できるようになります。

スクリプトにコメントを追加する

これは比較的単純なスクリプトですが、理解しやすくするため、コードにコメントを追加することをお勧めします。 コメントを使用して、スクリプトの目的を説明したり、主要なステップを特定したりできます。 これにより、他のユーザーがスクリプトを理解し、それぞれの目的に応じて修正しやすくなります。 また、しばらくしてから、コードを修正する必要が出てきた場合にも、コードを理解しやすくなります。

コメントは、1 つ以上のハッシュ文字から始まります。 コメントは、行頭に配置したり、コード行の末尾に追加したりできます。

  1. IDLE で、スクリプトの先頭に新しい行を追加します。
  2. 次のコメントをコピーして新しい行に貼り付けます。

    # Author: your name
    # Date: the date
    # Purpose: This script reads all the feature classes in a
    # geodatabase and copies them to a new feature dataset in
    # a new geodatabase. Feature classes not already in the
    # target coordinate system are projected.

  3. Author 行と Date 行を編集し、ユーザー名と現在の日付を追加します。
  4. import arcpy 行の前に、新たに 2 行を追加し、2 行目に次のコメントを追加します。

    # Imports

    空白行はコードに影響を与えることなく、コードを読みやすくします。 コメントは、このセクションがコードに必要なライブラリをインポートすることを示しています。 インポートは、一般的にスクリプトの先頭付近にまとめられています。

  5. import os 行の後に新たに 2 行を追加し、次のコメントを追加します。

    # Variables for paths, outputs, workspaces

    このコメントは、これらの変数が最初に設定される場所を示しています。

  6. arcpy.env.overwriteOutput = True 行の後に新たに 2 行を追加し、次のコメントを追加します。

    # Create a new geodatabase and dataset

  7. fcs = arcpy.ListFeatureClasses() 行の前に新たに 2 行を追加し、次のコメントを追加します。

    # Create a list of feature classes in the workspace

  8. if sr.factoryCode == 2248: 行の後、同じ行に次のコメントを追加します。

     # WKID of target coordinate system

    コードを説明するコメントを追加しました。

    次に、完全なコードを示します。

    # Author: your name
    # Date: the date
    # Purpose: This script reads all the feature classes in a
    # geodatabase and copies them to a new feature dataset in
    # a new geodatabase. Feature classes not already in the
    # target coordinate system are projected.
    
    # Imports
    import arcpy
    import os
    
    # Variables for paths, outputs, workspaces
    mypath = "C:/Lessons/PythonWorkflow"
    gdb = "Transportation.gdb"
    new_gdb = "Metro_Transport.gdb"
    fds = "Metro_Network"
    arcpy.env.workspace = os.path.join(mypath, gdb)
    arcpy.env.overwriteOutput = True
    
    # Create a new geodatabase and dataset
    new_gdb_path = arcpy.CreateFileGDB_management(mypath, new_gdb)
    print(f"The geodatabase {new_gdb} has been created.")
    arcpy.CreateFeatureDataset_management(new_gdb_path, fds, 2248)
    print(f"The feature dataset {fds} has been created.")
    
    # Create a list of feature classes in the workspace
    fcs = arcpy.ListFeatureClasses()
    for fc in fcs:
        desc = arcpy.da.Describe(fc)
        sr = desc["spatialReference"]
        new_fc = os.path.join(mypath, new_gdb, fds, fc)
        if sr.factoryCode == 2248: # WKID of target coordinate system
            arcpy.CopyFeatures_management(fc, new_fc)
            print(f"The feature class {fc} has been copied.")
        else:
            arcpy.Project_management(fc, new_fc, 2248)
            print(f"The feature class {fc} has been projected.")

    コメントを含む最終的なスクリプト

  9. スクリプトを保存します。

このチュートリアルでは、次の内容を学びました。

  • Python スクリプトを使用して、GIS ワークフローの反復タスクを自動化できます。
  • ArcPy には、データセットのリストを作成する関数が複数用意されています。
  • Python コードを使用してデータセットをリストおよび記述することで、ワークスペース内の GIS データセットの詳細なインベントリを作成することができます。 その後、各データセットの特性に基づいてさまざまな処理を実行することができます。
  • 出力を正しくするには、パスとファイル名を慎重に操作する必要があります。

また、Esri Press から出版されている Paul A. Zandbergen 博士による Python Scripting for ArcGIS ProAdvanced Python Scripting for ArcGIS Pro についても、ぜひお読みください。