同じフィーチャクラスの空間的に一致するフィーチャをマージする


8

互いに直接重なり合っているグリッドセル(ポリゴン15x15m)をプログラムでマージし、それらの属性のいくつかを追加する方法が必要です。

ArcGIS 10.1で、ポリゴンフィーチャクラスとして保存されたデータを使用しています。

データは、事前定義されたグリッド全体での歩行者調査の結果です。時々、歩行者調査を実施している人々は、コースから外れ、作業しているものに隣接する列または行に何かを記録します(またはGPS位置が移動します)。これにより、複数のGPSユニットからのデータが単一のフィーチャクラスに追加されると、各セルに対して2セットのデータが記録されます。各セルを調べて、重複する機能があるかどうかを確認し、それらの属性(整数、テキストなど)をマージして、マージされたデータを取得しなかった1つの機能を削除する方法が必要です。

「同一の削除」ツールと「同一の検索」ツールは、私が探していることを実行しません-フィーチャクラスには、10,000以上のフィーチャが含まれていることが多いため、手動で実行することはできません。

Pythonを使用してフィーチャクラスを反復処理し、その場所に重複するフィーチャがあるかどうかを確認する方法を知っています。どうすればよいかわからないのは、機能のマージと属性の更新です。誰かがこれを達成する方法について何らかの指示を提供できれば、私はそれを大いに感謝します。

編集-前/後の状態の詳細説明:下の図では、2つの機能が選択されています-同一の15x15メートルの正方形のポリゴン、すべての整数フィールド(プレフィックスとしてTOT_が付いているフィールド)を追加し、GPS_UNIT、INITIALSを追加する必要があります、およびREC_DATE文字列フィールド。

機能が直接重複しているため、表示するのは困難です。

ここに画像の説明を入力してください

編集2: XY中心を計算し、[X]& '、'&[Y]として文字列フィールドに連結して、データベースをアクセス可能にして、Find Duplicatesクエリを使用することで、重複するフィーチャを簡単に識別できることを発見しました複製されたセルを特定します。ただし、各セルの属性を1つの行にマージするための適切な方法を理解できていません。Pythonまたはデータベース環境でそれを行う方法のヘルプは大歓迎です!


1
「修正前後」の状態の小さなサンプル領域を投稿できますか?
blah238 2013年

回答:


2

マージしたい機能を反復して見つける方法を知っているので、おそらくarcpy.Dissovle_management()になる可能性のあるマージを実行する関数を作成します。ディゾルブを実行すると、おそらく集約パラメーターを使用して属性を結合し、それらのフィーチャーを元のフィーチャーから削除して、挿入カーソルでデータを更新できます。

どの機能を統合する必要があるかをどのように特定しますか?


これまでのところ、マージするフィーチャにIDを付ける最善の方法は、選択したフィーチャをソースとして使用し、レイヤーをターゲットとして使用して、反復して位置による選択を行うことです。次に、arcpy.getCountを使用して、選択されているフィーチャの数を確認します。複数ある場合は、選択されているすべてのフィーチャの属性を1つにマージし、他のフィーチャを削除する必要があります。
ケビン

2

Postgresに移行し、より強力なツールをいくつか手に入れてから、私はこの問題を解決することになりました。私の解決策は、同じGEOMフィールドを持つ余分なフィーチャを単に削除することでした-もちろん、1つを残して、フィールドワーク中に収集された他のデータから値を再計算しました。これにより、空間的に一致するフィーチャがなく、属性テーブルに正確な合計があるデータセットが得られました。私が使用した完全なPHPコードは以下のとおりです。Pythonでも同じことができると確信していますが、当時はPHPが最も簡単な方法でした。

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
    <title>TRU Recalculation</title>
</head>

<body>
    <!-- Progress bar holder -->
    <div id="progress" style="width:500px;border:1px solid #ccc;"></div>
    <!-- Progress information -->
    <div id="information" style="width"></div>

    <?php
        $tot_deb = 0;
        $mfr_tool = 0;
        $tot_ltool = 0;
        $tot_gs = 0;
        $tot_cerl = 0;
        $tot_cern = 0;
        $tot_fcr = 0;
        $tot_pfeat = 0;
        $tot_hist = 0;
        $tot_hfeat = 0;
        $tot_art = 0;

        $dbconn = pg_connect("host=localhost port=54321 dbname=sixksurvey user=postgres password=password");

        $TRU_set = pg_query($dbconn, "select gid, east, north, tot_deb, mfr_tool, tot_ltool, tot_gs, tot_cerl, tot_cern, tot_fcr, tot_pfeat, tot_hist, tot_hfeat, comment, tot_art, surf_sed, visibility, hdop, sats, gps_unit, initials, rec_date from trutest_full order by north asc");

        $total = pg_num_rows($TRU_set);
        $i = 1; //Just a counter for the progress bar

        if (pg_num_rows($TRU_set) > 0)
        {
            while($current_TRU = pg_fetch_row($TRU_set))
            {

                if ($current_TRU) 
                {
                    // Calculate the percent
                    $percent = intval($i/$total * 100)."%";

                    // Javascript for updating the progress bar and information
                    echo '<script language="javascript">
                    document.getElementById("progress").innerHTML="<div style=\"width:'.$percent.';background-color:#2CA25F;\">&nbsp;</div>";
                    document.getElementById("information").innerHTML="'.$i.' TRU Cells Recalculated.";
                    </script>';

                    // Select all the LITHICS within the current TRU and count them up according to their types, then assign the new count to the relevant total variable.
                    $ALL_Lithics = pg_query($dbconn,"SELECT type, art_count FROM lithic join trutest_full ON ST_CONTAINS(trutest_full.geom, lithic.geom) WHERE trutest_full.gid = " . $current_TRU[0]);
                    while($current_LITHIC = pg_fetch_row($ALL_Lithics))
                    {
                        //If statement for tot_deb
                        if ($current_LITHIC[0] == 'Angular Debris' or $current_LITHIC[0] == 'Biface Thinning Flake' or $current_LITHIC[0] == 'Hammer stone')
                        {
                            $tot_deb += $current_LITHIC[1];
                        }

                        //If statement for mfr_tool
                        if ($current_LITHIC[0] == 'Test Nod/Core' or $current_LITHIC[0] == 'Reduced Core' or $current_LITHIC[0] == 'Core Red. Flake')
                        {
                            $mfr_tool += $current_LITHIC[1];
                        }
                        //If statement for tot_ltool
                        if ($current_LITHIC[0] == 'Scraper' or $current_LITHIC[0] == 'Uniface' or $current_LITHIC[0] == 'Retouched Tool' or
                            $current_LITHIC[0] == 'Proj. Point' or $current_LITHIC[0] == 'Biface' or $current_LITHIC == 'Other')
                        {
                            $tot_ltool += $current_LITHIC[1];
                        }
                    }


                    // Select all the CERAMICS within the current TRU and count them up according to their types, then assign the new count to the relevant total variable.
                    $ALL_Ceramics = pg_query($dbconn,"SELECT type, art_count FROM ceramic JOIN trutest_full ON ST_CONTAINS(trutest_full.geom, ceramic.geom) WHERE trutest_full.gid = " . $current_TRU[0]);
                    while($current_CERAMIC = pg_fetch_row($ALL_Ceramics))
                    {
                        // Calculate new total for Local Ceramics
                        if ($current_CERAMIC[0] == 'EP Brown' or $current_CERAMIC[0] == 'EP brownware' or $current_CERAMIC[0] == 'EP Poly' or $current_CERAMIC[0] == 'EP Decorated' or $current_CERAMIC[0] == 'EP UB' or $current_CERAMIC[0] == 'Jornada Brown' or $current_CERAMIC[0] == 'EP Bichrome')
                        {
                            $tot_cerl += $current_CERAMIC[1];
                        }

                        // Calculate new total for Non-Local Ceramics
                        else
                        {
                            $tot_cern += $current_CERAMIC[1];
                        }
                    }
                    // Select all the FCR within the current TRU and count them up according to their types, then assign the new count to the relevant total variable.
                    $ALL_fcr = pg_query($dbconn,"SELECT art_count FROM fcr JOIN trutest_full ON ST_CONTAINS(trutest_full.geom, fcr.geom) WHERE trutest_full.gid = " . $current_TRU[0]);
                    while($current_FCR = pg_fetch_row($ALL_fcr))
                    {
                        $tot_fcr += $current_FCR[0];
                    }               

                    // Select all the FEATURES within the current TRU and count them up 
                    $ALL_features = pg_query($dbconn,"SELECT type FROM fcr JOIN trutest_full ON ST_CONTAINS(trutest_full.geom, fcr.geom) WHERE trutest_full.gid = " . $current_TRU[0]);
                    while($current_Feat = pg_fetch_row($ALL_features))
                    {
                        // Test the type of the feature to identify the historic features (I started here because there are fewer types, this is faster).  Rather than try to count the rows,
                        // I just add 1 to each total for each feature that is being tested
                        if ($current_Feat[0] == 'Historic Artifact Conc.' or $current_Feat[0] == 'Historic Water Feature' or $current_Feat[0] == 'Historic Structure')
                        {
                            $tot_hfeat += 1;    
                        }
                        else
                        {
                            $tot_pfeat += 1;
                        }
                    }
                    // Select all the GS within the current TRU and count them up 
                    $ALL_gs = pg_query($dbconn,"SELECT art_count FROM gs JOIN trutest_full ON ST_CONTAINS(trutest_full.geom, gs.geom) WHERE trutest_full.gid = " . $current_TRU[0]);
                    while($current_GS = pg_fetch_row($ALL_gs))
                    {
                        $tot_gs += $current_GS[0];
                    }   

                    // Select all the HISTORIC within the current TRU and count them up according to their types, then assign the new count to the relevant total variable.
                    $ALL_historic = pg_query($dbconn,"SELECT art_count FROM historic JOIN trutest_full ON ST_CONTAINS(trutest_full.geom, historic.geom) WHERE trutest_full.gid = " . $current_TRU[0]);
                    while($current_HISTORIC = pg_fetch_row($ALL_historic))
                    {
                        $tot_hist += $current_HISTORIC[0];
                    }   

                    // Count all the artifacts and assign to TOT_ART
                    $tot_art = $tot_deb + $mfr_tool + $tot_ltool + $tot_cerl + $tot_cern + $tot_fcr + $tot_hist + $tot_gs;

                    // Something here to merge initials/date recorded/surface/visibiilty/etc into the comments for merged cells
                    // This code isn't the place to do this...  //Not dealing with duplicates here, just every cell in the set...


                    // Send the updated counts back to the database.
                    $result = pg_query($dbconn,"UPDATE trutest_full SET tot_deb = " . $tot_deb . ", mfr_tool = " . $mfr_tool . ", tot_ltool = " . $tot_ltool . ", tot_gs = " . $tot_gs . ", tot_cerl = " . $tot_cerl . ", tot_cern = " . $tot_cern . ", tot_fcr = " . $tot_fcr . ", tot_pfeat = " . $tot_pfeat . ", tot_hist = " . $tot_hist . ", tot_hfeat = " . $tot_hfeat . ", tot_art = " . $tot_art . " WHERE trutest_full.gid = " . $current_TRU[0]);

                    // This is for the buffer achieve the minimum size in order to flush data
                    echo str_repeat(' ',1024*64);

                    // Send output to browser immediately
                    flush();

                    if (!$result)
                    {
                        echo 'Update Query Failed in TRU.gid = ' . $current_TRU[0];
                    }

                    // Zero out all the hoppers for the next go-round
                    $tot_deb = 0;
                    $mfr_tool = 0;
                    $tot_ltool = 0;
                    $tot_gs = 0;
                    $tot_cerl = 0;
                    $tot_cern = 0;
                    $tot_fcr = 0;
                    $tot_pfeat = 0;
                    $tot_hist = 0;
                    $tot_hfeat = 0;
                    $tot_art = 0;

                    $i += 1;
                }
            }
        }
        echo 'TRU Recalculate Done';
    ?>

</body>
</html>

0

同一のセル(実際にはポリゴン)の属性のみをマージしたいので、Unionを使用してすべての属性を保持します。このようにして、結果のすべてのポリゴン(セル)を反復処理し、元の属性の両方のセットにアクセスして、必要な新しい値を書き込むことができます。同じ属性名が両方の元のフィーチャクラスで使用されている場合、Unionの前にフィールドの名前を変更して、両方を引き続き使用できるようにする必要がある場合があります。

実際、質問をもう一度読むと、入力フィーチャクラスが1つしかないことがわかります。ここで説明するように、Unionは単一のフィーチャクラスに対して実行できるため、依然として有用である可能性があります


各GPSユニットからのデータを組み合わせるときに、Appendの代わりにUnionを使用することを考えていませんでした...これを行うと、空間的なオーバーラップの問題がなくなり、簡単に対処する必要があります。一度に20以上のフィーチャクラスを結合するときに発生する可能性のある問題についての考えはありますか?
Kevin

一度に実行したい場合は、おそらくAdvanced(ArcInfo)ライセンスが必要です。基本と標準では、ユニオンをペアで実行して結果を集計する必要があります。
PolyGeo
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.