Fusionar entidades espacialmente coincidentes en la misma clase de entidad

8

Necesito una forma de fusionar programáticamente celdas de cuadrícula (polígono 15x15m) que están directamente una encima de la otra y sumar algunos de sus atributos.

Estoy trabajando en ArcGIS 10.1 con los datos almacenados como una clase de entidad poligonal.

Los datos son el resultado de un estudio de peatones en una cuadrícula predefinida. En ocasiones, las personas que realizan la inspección de peatones se desvían y graban algo en una columna o fila adyacente a la que están trabajando (o la posición del GPS se desvía). Esto da como resultado que se registren dos conjuntos de datos para cada celda cuando los datos de múltiples unidades GPS se agregan en una sola clase de entidad. Necesito una forma de recorrer cada celda, verificar si hay características duplicadas, si luego se combinan sus atributos (algunos enteros, algunos textos), y luego elimine la única característica que no obtuvo los datos combinados.

Las herramientas 'Eliminar idéntico' y 'Buscar idéntico' no hacen lo que estoy buscando, y hacerlo manualmente no es una opción ya que la clase de entidad a menudo tiene más de 10,000 características.

Sé cómo iterar a través de la clase de entidad usando Python y verificar para determinar si hay entidades duplicadas en esa ubicación. Lo que no sé hacer es tratar de fusionar las características y actualizar los atributos. Si alguien puede ofrecer alguna dirección sobre cómo lograr esto, lo agradecería enormemente.

EDITAR - Más descripción del estado Antes / Después: en la imagen a continuación hay dos características seleccionadas: polígonos cuadrados idénticos de 15x15 metros, necesito agregar todos los campos enteros (los que tienen TOT_ como prefijo) y agregar GPS_UNIT, INICIALES , y campos de cadena REC_DATE.

Es difícil de mostrar ya que las características se superponen directamente.

ingrese la descripción de la imagen aquí

EDITAR 2: descubrí que puedo identificar fácilmente las características duplicadas calculando sus centros XY, concatenándolos en un campo de cadena como [X] & ',' & [Y] y luego abriendo la base de datos en acceso y usando una consulta Buscar duplicados para identificar cuáles de las células se han duplicado. Sin embargo, no he podido encontrar una buena manera de fusionar los atributos para cada una de las celdas en una sola fila. ¡Ayuda con cómo hacerlo, ya sea en python o en un entorno de base de datos, sería muy bienvenido!

Kevin
fuente
1
¿Puede publicar un área de muestra pequeña con estados de "antes y después de la corrección"?
blah238

Respuestas:

2

Como sabe cómo iterar y encontrar las características que desea fusionar, crearía una función para hacer la fusión que probablemente podría ser arcpy.Dissovle_management (). Disuelva y probablemente pueda usar los parámetros de agregación para combinar los atributos, luego elimine esas características del original y actualice los datos nuevamente con un cursor de inserción.

¿Cómo identifica qué características deben fusionarse?

Justin
fuente
Hasta ahora, la mejor manera de fusionar las características de ID es iterar y hacer una selección por ubicación utilizando la característica seleccionada como origen y la capa como destino. Luego, uso arcpy.getCount para ver cuántas características están seleccionadas, si es más de una, entonces necesito fusionar los atributos de todas las características seleccionadas en una y eliminar las otras.
Kevin
2

Terminé resolviendo este problema después de migrar a Postgres y tener algunas herramientas más poderosas a la mano. Mi solución fue simplemente eliminar características adicionales con campos GEOM idénticos, dejando una, por supuesto, y luego recalcular los valores de los otros datos recopilados durante el trabajo de campo. Esto me dio un conjunto de datos sin características espacialmente coincidentes y totales precisos en las tablas de atributos. El código PHP completo que utilicé está debajo; Estoy seguro de que lo mismo podría lograrse en Python, pero PHP era la ruta más fácil para mí en ese momento.

    <!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>
Kevin
fuente
0

Como solo desea fusionar atributos para celdas (en realidad polígonos) que son idénticos, usaría Union y mantendría todos los atributos. De esa manera, puede recorrer todos los polígonos (celdas) resultantes y tener acceso a ambos conjuntos de atributos originales para escribir los nuevos valores que desee. Si ambas clases de entidad originales utilizan los mismos nombres de atributo, es posible que deba cambiar el nombre de los campos antes de la Unión para que ambos permanezcan disponibles.

En realidad, una rápida relectura de su pregunta me dice que solo tiene una clase de entidad de entrada. La unión aún puede ser útil porque puede ejecutarse contra una única clase de entidad como se describe aquí .

PolyGeo
fuente
No había pensado usar Union en lugar de Append al combinar los datos de cada unidad GPS ... Hacer eso eliminaría el problema de la superposición espacial y luego tendría que lidiar con lo más fácil. ¿Alguna idea sobre los problemas que pueden surgir al unir más de 20 clases de entidad a la vez?
Kevin
Solo que probablemente necesite tener una licencia Avanzada (ArcInfo) si desea hacerlo de una vez. Con Basic y Standard necesitaría hacer Uniones en pares y agregar los resultados.
PolyGeo