GIS奮闘記

元GISエンジニアの技術紹介ブログ。主にPythonを使用。

スポンサーリンク

ArcPyを使用してフィーチャクラスの情報をCSV出力する

さて、本日は「ArcPyを使用してフィーチャクラスの情報をCSV出力する」です。実際に業務では数十個のフィーチャクラスがあり、それぞれにサブタイプなどを設定していたりします。例えば、サブタイプごとのアイテム数を抽出したい場合、一つ一つ確認していくのは現実的ではありません。そういった場合に対応するPythonスクリプトを書いてみました。恥ずかしながら最近Gistを使い始めたので、そこにもアップしてみました。
フィーチャクラスのサブタイプごとのアイテム数を取得するスクリプト(複数のGDBには対応していません) · GitHub

データ

以下のようなGDBとフィーチャクラスを作成しました。

f:id:sanvarie:20160209161731p:plain

各フィーチャクラスのサブタイプ設定です。PIPEフィーチャクラスはサブタイプ設定なしにしました。
■BOUNDARY
f:id:sanvarie:20160209162044p:plain

■CHARACTER
f:id:sanvarie:20160209162348p:plain

■LANDMARK
f:id:sanvarie:20160209162621p:plain

■PIPE
f:id:sanvarie:20160209162650p:plain

■ROAD
f:id:sanvarie:20160209162730p:plain

インストール

ArcMapがインストールされていればNumpyはインストール済だと思いますので、Pandasのインストールをお願いします。

サンプルコード

各フィーチャクラスもしくはフィーチャクラスのサブタイプごとのアイテム数をCSV出力するPythonスクリプトです。

以下の項目を出力します。
gdb
・レイヤ名
エイリアス
・ジオメトリタイプ
・サプタイプ
・アイテム数

# -*- coding: utf-8 -*-
import arcpy
from os.path import join
import pandas as pd
import numpy as np

def getInfo(dataSource,fList):

    #サブタイプを取得
    subtypefields = arcpy.da.ListSubtypes(dataSource)
    subDict = {}
    for name in subtypefields.keys():
        groupDict = subtypefields[name]
        for stkey in list(groupDict.keys()):
            if stkey == 'SubtypeField':

                fields = groupDict[stkey]

                #サブタイプが設定されていない場合
                if fields == "":
                    outputstring = fList[0] \
                                   + "," + fList[1] \
                                   + "," + fList[2] \
                                   + "," + fList[3] \
                                   + "," + "" \
                                   + "," + str(fList[4]) + "\n"

                    f.write(outputstring.encode("SHIFT-JIS"))

                #サブタイプが設定されている場合
                else:
                    for stkey in list(groupDict.keys()):
                        if stkey == 'Name':

                            #フィーチャをnumpyに変換してpandasに格納
                            column = arcpy.da.FeatureClassToNumPyArray(dataSource,("SUBTYPE_CD"),null_value=-9999)
                            dfWater = pd.DataFrame(column)

                            fields = groupDict[stkey]
                            subDict[fields] = name

                            #サブタイプごとのデータを抽出
                            dfWaterValue = pd.DataFrame(dfWater[dfWater.SUBTYPE_CD == subDict[fields]])

                            outputstring = fList[0] \
                                           + "," + fList[1] \
                                           + "," + fList[2] \
                                           + "," + fList[3] \
                                           + "," + fields \
                                           + "," + str(len(dfWaterValue)) + "\n"

                            f.write(outputstring.encode("SHIFT-JIS"))

# ファイルの出力先を指定
f = open(r"D:\python\featureclass/list.csv", "w")

# 対象のGDBが格納されているフォルダ
folder = 'C:\ArcPySample'
gdb = "ArcPyTest.gdb"
data = join(folder,gdb)

# ファイルにヘッダを出力
outputstring = u"GDB,レイヤ名,エイリアス,ジオメトリタイプ,サブタイプ,アイテム数\n"
f.write(outputstring.encode("SHIFT-JIS"))

arcpy.env.workspace = data

# フィーチャクラスから属性を取得
for fc in arcpy.ListFeatureClasses():

    fList = []

    dataSource = join(data,fc)

    #フィーチャクラスの名称を取得
    name = arcpy.Describe(dataSource).Name
    #フィーチャクラスのエイリアスを取得
    aliasName = arcpy.Describe(dataSource).AliasName
    #フィーチャの件数取得
    cnt = arcpy.GetCount_management(dataSource)
    #フィーチャタイプ取得
    fType = arcpy.Describe(dataSource).FeatureType
    #ジオメトリタイプ取得
    gType = arcpy.Describe(dataSource).shapeType
    #アノテーションの場合(アノテーションのジオメトリタイプはポリゴンになってしまうのでこの処理を追加)
    if fType == "Annotation":
        gType = "Annotation"

    fList.append(gdb)
    fList.append(name)
    fList.append(aliasName)
    fList.append(gType)
    fList.append(int(cnt.getOutput(0)))

    getInfo(dataSource,fList)

f.close()

結果を確認します。
f:id:sanvarie:20160209170233p:plain

各フィーチャクラスもしくはフィーチャクラスのサブタイプごとのアイテム数が出力されましたね。GDB複数存在する場合はちょっとプログラムを変更する必要がありますが、このような感じで既存のデータのアイテム数を知ることが出来ます。アイテム数だけではなく、知りたい項目に合わせてプログラムを修正することもできますね。

簡単ではありますが、本日は以上です!