¿Exportando solo ciertas columnas a un archivo CSV en ArcGIS for Desktop?

15

He escrito un script de python usando arcpy que genera una clase de entidad poligonal en una geodatabase de archivos. He añadido una función para exportar los atributos a un archivo CSV separado. Estoy utilizando el código que he encontrado en esta publicación que funciona perfectamente. Sin embargo, ese código exporta cada columna en la clase de entidad. Solo quiero exportar los campos que no tienen los siguientes nombres: OBJECTID , Shape o Shape_Length .

Mi archivo CSV se genera correctamente, y correctamente no incluye los campos OBJECTID o Shape_Length . Sin embargo, el campo Shape está escrito en el archivo. Un valor de ejemplo que se escribe en ese campo es:

<geoprocessing describe geometry object object at 0x28CB90A0>

He agregado una línea para imprimir los nombres de los campos a medida que se itera a través de ellos y, sorprendentemente, no se imprime Shape . Es como si ArcGIS lo estuviera ocultando o le diera un nombre diferente.

El código para mi función es el siguiente:

def exportToTable():
    """ 
        Exports the final outputs to a CSV File.
    """

    # Create path to CSV File (note the varialbe outputPath is declared elsewhere).
    CSVFile = outputPath+'\FinalOutput.csv'
    arcpy.AddMessage("Created CSV File: %s" %CSVFile)

    # Get all fields in FinalOutput feature class and remove unwanted fields.
    fields = arcpy.ListFields('FinalOutput')
    for field in fields:
        arcpy.AddMessage("Field.name is:"+field.name) #not printing 'Shape' field name
        if field.name in (['OBJECTID', 'Shape', 'Shape_Length']):
            fields.remove(field)

    i = 1
    f=open(CSVFile, 'w')
    for field in fields:
        #--write the wanted field names to the output file
        if i < len(fields):
            f.write('%s,' % field.name)
            i += 1
        else:
            f.write('%s\n' % field.name)

    # Use a search cursor to iterate through the rows of the table and write them to the CSV file.
    rows = arcpy.SearchCursor('FinalOutput')
    for row in rows:
        i = 1
        for field in fields:
            if i < len(fields):
                f.write('%s,' % row.getValue(field.name))
                i += 1
            else:
                f.write('%s\n' % row.getValue(field.name))
    del rows
    f.close()

¿Alguien sabe lo que está pasando aquí?

Modifiqué mi código para seguir los consejos de @sgrieve y aún estaba escribiendo el campo Shape . Si agrego una línea para imprimir los nombres de los campos a medida que se iteran a través de ellos, enumera todos los campos except el campo Shape , pero aún se escribe en el CSV. También agregó las coordenadas X e Y del polígono como dos columnas nuevas y las columnas ya no están alineadas con los nombres de las columnas.

He modificado la línea donde @sgrieve declara que los campos son los siguientes:

fields = [f.name for f in arcpy.ListFields('FinalCadastre') if f.type <> 'Geometry']

El nuevo código funciona bien, pero todavía no estoy seguro de cuál fue el problema. ¿Alguien sabe lo que estaba pasando? ¿Cuál es el trato con el campo Shape ?

    
pregunta Fezter 28.11.2012 - 07:23

3 respuestas

14

He simplificado su código y corregido el error utilizando da módulo introducido en 10.1. Agiliza en gran medida la lectura de datos usando cursores, y se usa junto con el comando with , este código debería ser más estable que si usara el método más antiguo de acceso a archivos.

Funciona al hacer una lista de todos los campos y luego eliminar los campos que no desea de la lista. Esto podría hacerse dentro de la lista de comprensión, pero sería bastante desordenado y no-pythonic. Una vez que se ha creado la lista de campos deseados, se utiliza con el módulo da para leer todos los datos de estos campos en el cursor. Luego se puede pasar y escribir en el archivo usando otra comprensión de lista para unir todos los campos. Esto tiene la ventaja de trabajar para cualquier número de campos mayor que 0.

import arcpy

fc = 'C:\antenna_shp\cables.shp'
CSVFile = 'C:\antenna_shp\FinalOutput.csv'

fields = [f.name for f in arcpy.ListFields(fc)]

for i,f in enumerate(fields):
    if f == 'Shape' or f == 'Shape_Length' or f == 'OBJECTID':
        del fields[i]

with open(CSVFile, 'w') as f:
    f.write(','.join(fields)+'\n') #csv headers
    with arcpy.da.SearchCursor(fc, fields) as cursor:
        for row in cursor:
            f.write(','.join([str(r) for r in row])+'\n')
    
respondido por el sgrieve 28.11.2012 - 10:38
2

Creo que me encontré con el mismo problema y descubrí la razón por la que no se eliminó el campo "Forma". Al usar este bucle:

if field.name in (['OBJECTID', 'Shape', 'Shape_Length']):
    fields.remove(field)

Descubrí que en realidad solo se están eliminando todos los demás campos. Por lo tanto, primero pasará en bucle, eliminará 'OBJECTID', y luego el campo 'Shape' irá al lugar que anteriormente tenía 'OBJECTID' en la lista, por lo que se moverá al siguiente, que sería 'Shape_Length'.

Por lo tanto, no fue específicamente la geometría de la forma la que evitó que se eliminara, solo el hecho de que elimina todos los demás campos cuando se usa este script.

    
respondido por el Sara Flecher 22.08.2014 - 22:28
0

Una clave para un aspecto de esto es determinar el nombre correcto para los campos no definidos por el usuario de la identificación y la geometría del objeto. El tipo de campo de geometría es Doble, lo que no es útil en este caso. Usando la función de describir, se puede determinar el nombre apropiado para estos campos en todos los tipos de archivos (es decir, shapefile v file gdb, etc; aliviar la gran cantidad de problemas como el oid cambiará incluso dentro del mismo tipo de archivo a veces ...).

fc = 'path to my featureclass'
desc = arcpy.Describe(fc)
fields = [f.name for f in arcpy.ListFields(fc) if f.name not in (desc.OIDFieldName, desc.areaFieldName, desc.lengthFieldName), desc.shapeFieldName)]
    
respondido por el David Richey 28.07.2016 - 22:49

Lea otras preguntas en las etiquetas