Zusammenführen räumlich übereinstimmender Features in derselben Feature-Class


8

Ich brauche eine Möglichkeit, Rasterzellen (Polygon 15x15m), die direkt übereinander liegen, programmgesteuert zusammenzuführen und einige ihrer Attribute zu addieren.

Ich arbeite in ArcGIS 10.1 mit den Daten, die als Polygon-Feature-Class gespeichert sind.

Die Daten sind das Ergebnis einer Fußgängerbefragung über ein vordefiniertes Raster. Gelegentlich verlassen die Leute, die die Fußgängervermessung durchführen, den Kurs und zeichnen etwas in einer Spalte oder Zeile neben der auf, in der sie arbeiten (oder die GPS-Position wandert). Dies führt dazu, dass zwei Datensätze für jede Zelle aufgezeichnet werden, wenn die Daten von mehreren GPS-Einheiten an eine einzelne Feature-Class angehängt werden. Ich brauche einen Weg, um durch jede Zelle zu gehen, zu überprüfen, ob es doppelte Features gibt, ob es dann ihre Attribute zusammenführt (eine Ganzzahl, ein Text), und dann das eine Feature zu löschen, das die zusammengeführten Daten nicht erhalten hat.

Die Tools "Identisch löschen" und "Identisch suchen" machen nicht das, wonach ich suche - und es manuell zu tun ist keine Option, da die Feature-Class häufig mehr als 10.000 Features enthält.

Ich weiß, wie man die Feature-Class mit Python durchläuft und prüft, ob sich an dieser Stelle doppelte Features befinden. Ich weiß nicht, wie ich die Features zusammenführen und die Attribute aktualisieren soll. Wenn jemand eine Anleitung dazu geben kann, würde ich es sehr schätzen.

BEARBEITEN - Weitere Beschreibung des Vorher / Nachher-Status: In der Abbildung unten sind zwei Funktionen ausgewählt - identische 15 x 15 Quadratmeter große Polygone. Ich muss alle ganzzahligen Felder (die mit TOT_ als Präfix) addieren und die GPS_UNIT, INITIALS anhängen und REC_DATE-Zeichenfolgenfelder.

Es ist schwierig zu zeigen, da sich die Features direkt überlappen.

Geben Sie hier die Bildbeschreibung ein

BEARBEITEN 2: Ich habe festgestellt, dass ich die duplizierten Features leicht identifizieren kann, indem ich ihre XY-Zentren berechne, sie zu einem Zeichenfolgenfeld als [X] & ',' & [Y] verkette, dann die Datenbank beim Zugriff öffne und eine Abfrage zum Suchen von Duplikaten verwende um zu identifizieren, welche der Zellen dupliziert wurden. Es ist mir jedoch nicht gelungen, einen guten Weg zu finden, um die Attribute für jede der Zellen in einer einzigen Zeile zusammenzuführen. Hilfe dabei, entweder in Python oder in einer Datenbankumgebung, wäre sehr willkommen!


1
Können Sie einen kleinen Stichprobenbereich mit den Zuständen "vor und nach der Korrektur" veröffentlichen?
blah238

Antworten:


2

Da Sie wissen, wie Sie die Features, die Sie zusammenführen möchten, iterieren und finden, würde ich eine Funktion erstellen, um die Zusammenführung durchzuführen, die wahrscheinlich arcpy.Dissovle_management () sein könnte. Wenn Sie die Auflösung durchführen, können Sie wahrscheinlich die Aggregationsparameter verwenden, um die Attribute zu kombinieren. Löschen Sie dann diese Features aus dem Original und aktualisieren Sie die Daten mit einem Einfügecursor zurück.

Wie erkennen Sie, welche Funktionen zusammengeführt werden müssen?


Bisher ist der beste Weg, um Features zum Zusammenführen zu identifizieren, das Durchlaufen und Auswählen nach Standort, wobei das ausgewählte Feature als Quelle und die Ebene als Ziel verwendet werden. Dann verwende ich arcpy.getCount, um zu sehen, wie viele Features ausgewählt sind. Wenn es mehr als eines ist, muss ich die Attribute aller ausgewählten Features zu einem zusammenführen und die anderen löschen.
Kevin

2

Nachdem ich zu Postgres migriert war und einige leistungsfähigere Tools zur Hand hatte, löste ich dieses Problem. Meine Lösung bestand darin, einfach zusätzliche Features mit identischen GEOM-Feldern zu löschen - natürlich eines zu belassen und dann die Werte aus den anderen Daten neu zu berechnen, die während der Feldarbeit gesammelt wurden. Dies gab mir einen Datensatz ohne räumlich übereinstimmende Merkmale und genaue Summen in den Attributtabellen. Der vollständige PHP-Code, den ich verwendet habe, ist unten; Ich bin mir sicher, dass das Gleiche in Python erreicht werden kann, aber PHP war zu dieser Zeit der einfachste Weg für mich.

    <!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

Da Sie nur Attribute für Zellen (tatsächlich Polygone) zusammenführen möchten, die identisch sind, würde ich Union verwenden und alle Attribute beibehalten. Auf diese Weise können Sie alle resultierenden Polygone (Zellen) durchlaufen und auf beide Sätze von Originalattributen zugreifen, um die gewünschten neuen Werte zu schreiben. Wenn beide ursprünglichen Feature-Classes dieselben Attributnamen verwenden, müssen Sie möglicherweise Felder vor der Union umbenennen, damit beide verfügbar bleiben.

Ein kurzes erneutes Lesen Ihrer Frage zeigt mir, dass Sie nur eine Eingabe-Feature-Class haben. Union kann weiterhin nützlich sein, da es wie hier beschrieben für eine einzelne Feature-Class ausgeführt werden kann .


Ich hatte nicht daran gedacht, Union anstelle von Append zu verwenden, wenn ich die Daten von jedem GPS-Gerät kombiniere ... Dadurch würde das Problem der räumlichen Überlappung beseitigt und ich müsste mich nur um das Einfachere kümmern. Irgendwelche Gedanken zu Problemen, die auftreten können, wenn mehr als 20 Feature-Classes gleichzeitig gewerkschaftlich organisiert werden?
Kevin

Nur, dass Sie wahrscheinlich über eine erweiterte Lizenz (ArcInfo) verfügen müssen, wenn Sie dies auf einmal tun möchten. Mit Basic und Standard müssten Sie Gewerkschaften paarweise durchführen und die Ergebnisse aggregieren.
PolyGeo
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.