GIS奮闘記

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

スポンサーリンク

ArcPyレシピ集⑤ ~重複したフィーチャを抽出~

さて、本日は久しぶりにArcPyについて書いてみようと思います。

ArcPyとは

言わずもがなですが、ArcGISのデータを扱うためのPythonライブラリです。ArcPyに関しては当ブログで色々紹介していますので、興味のある方は以下エントリーを読んでみてください。

www.gis-py.com

www.gis-py.com

今回のゴール

GISデータを扱っているとたまに空間的に重複したデータに出くわすことがあります。こういった無駄なデータがあるとデータが重くなるだけでなく、システムの不具合の原因になる可能性もあります。今回はこういったデータを一括で抽出する方法を紹介しようと思います。

環境

Windows10 64bit
ArcGIS10.4.1
Python2.7.3

サンプルデータ

以下のようにポイントフィーチャクラス(平面直角座標系9系(JGD2000))を作成しました。
f:id:sanvarie:20190131100741p:plain

また、以下のようにポイントを作図しました(何点か重複している状態です)。

※「Key」カラムはキーとなるカラムと見立てて作りました。

f:id:sanvarie:20190131101841p:plain

サンプルコード

上記データの中にある重複したポイントデータを抽出するサンプルコードです。
(「Key」カラムの中身を出力します。)

# -*- coding: utf-8 -*-
import arcpy
from collections import Counter

class DuplicateGeometry(object):

    def  __init__(self):
        arcpy.env.workspace = ur"D:\gis-py\arcpy\data\SampleData.gdb"
        self.feature_class = u"SamplePoint"

    def check_dupulicate_feature(self):
        """重複しているフィーチャのFEAT_NUMをリストで返します

        arguments:
        none

        returns:
        duplicated_list -- FEAT_NUMのリスト

        """

        try:
            feature_list = []
            features_num_geo = []
            duplicated_list = []

            features = (row for row in arcpy.da.SearchCursor(self.feature_class, "SHAPE@XY"))
            feature_list = self.extract_data(features)
            features_num_geo = (row for row in arcpy.da.SearchCursor(self.feature_class, ["Key","SHAPE@XY"]))

            for ps in features_num_geo:
                for pl in feature_list:
                    if pl[0] == ps[1][0] and pl[1] == ps[1][1]:

                        duplicated_list.append(ps[0]) #重心XYが一致した場合FEAT_NUMを格納

        except Exception:
            return None
        else:
            return duplicated_list

    def extract_data(self,features):
        #重心XYが重複しているデータを抽出
        c = Counter(tuple(items) for items in features for items in items)
        return [items for items, count in c.most_common() if count > 1]

if __name__ == '__main__':
    d = DuplicateGeometry()
    duplicate_geometry = d.check_dupulicate_feature()
    print duplicate_geometry

実行すると以下のような結果になりました。
f:id:sanvarie:20190131102140p:plain

データを確認してみると、以下画像のようにポイントが重複していることがわかります。
f:id:sanvarie:20190131102317p:plain

今回抽出した他のデータも同様の状態ですが、同じような画像を貼り付けるだけになってしまうので、今回は割愛します。

このソースだとデータが多い時に少し時間がかかってしまうのが難ですね。もう少し効率の良い方法があればそれも今後紹介できればと思います。

今回はArcPyを使いましたが、ArcMapでも同様のことはできるかと思います。

例えば・・・
①対象のフィーチャクラスに「X」「Y」というカラムを追加
②ジオメトリ演算でそれぞれにXとYの座標を付与(以下画像参照)
③「②」のデータをEXCELか何かで重複チェック

f:id:sanvarie:20190131104119p:plain

これで同じ結果が得られるかと思います。

ArcGISユーザーだけど、ArcPyは敷居が高くてなかなか手が出せないという方もいらっしゃるかと思います。ただ、とても便利なライブラリなので、ぜひ使ってみてください。何かお困りのことがあれば、それに関するコメントを残していただければできる限り回答いたします(私にわかる範囲でですが)

簡単にではありますが、今回は以上です。