Esportare solo determinate colonne nel file CSV in ArcGIS per desktop?


15

Ho scritto uno script Python usando arcpy che genera una classe caratteristica poligonale in un file geodatabase. Ho aggiunto una funzione per esportare gli attributi in un file CSV separato. Sto usando il codice che ho trovato in questo post che funziona perfettamente. Tuttavia, quel codice esporta ogni colonna nella classe caratteristica. Ho solo voglia di esportare i campi che non hanno i seguenti nomi: OBJECTID, Shapeo Shape_Length.

Il mio file CSV viene generato correttamente e non include correttamente i campi OBJECTIDo Shape_Length. Tuttavia, il Shapecampo è scritto nel file. Un valore di esempio scritto in quel campo è:

<geoprocessing describe geometry object object at 0x28CB90A0>

Ho aggiunto una riga per stampare i nomi dei campi mentre scorre attraverso di essi e, sorprendentemente, Shapenon viene stampato. È come se ArcGIS lo nascondesse o gli assegnasse un nome diverso.

Il codice per la mia funzione è di seguito:

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()

Qualcuno sa cosa sta succedendo qui?


Ho modificato il mio codice per seguire il consiglio di @sgrieve e stava ancora scrivendo il Shapecampo. Se aggiungo una riga per stampare i nomi dei campi mentre scorre attraverso di essi, elenca tutti i campi tranne il Shapecampo, eppure scrive ancora nel CSV. Ha anche aggiunto le coordinate X e Y del poligono come due nuove colonne e le colonne non sono più allineate con i nomi delle colonne.

Ho modificato la riga in cui @sgrieve dichiara che i campi sono i seguenti:

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

Il nuovo codice funziona bene, ma non sono ancora sicuro di quale sia stato il problema. Qualcuno sa cosa stava succedendo? Qual è il problema con il Shapecampo?


Devi usare Python qui? È molto facile nascondere i campi che non desideri utilizzando la scheda Campi delle proprietà del livello. Quindi dalla tabella degli attributi aperta Esporta i dati in formato file di testo (che è CSV) per ottenere solo i campi desiderati.
PolyGeo

Sì, voglio che questo venga aggiunto al mio script. È un requisito del cliente.
Fezter

Qualcun altro sa cosa sta succedendo qui? Qualcuno sa perché il Shapecampo è stato scritto nel file? Mentre il codice di @Schrieve probabilmente ha migliorato il mio codice, non ha risolto il problema.
Fezter

1
Il mio approccio a questo sarebbe di usare MakeTableView seguito da TableToTable . Se il tuo approccio non ci arriva, questo potrebbe essere un altro modo per "perdere" il tuo campo Shape.
PolyGeo

Risposte:


14

Ho semplificato il tuo codice e corretto l'errore utilizzando il modulo da introdotto in 10.1. Semplifica notevolmente la lettura dei dati mediante i cursori e, utilizzato insieme al withcomando, questo codice dovrebbe essere più stabile rispetto a quando utilizzava il vecchio metodo di accesso ai file.

Funziona creando un elenco di tutti i campi e quindi rimuovendo i campi che non si desidera dall'elenco. Questo potrebbe essere fatto all'interno della comprensione dell'elenco, ma sarebbe piuttosto disordinato e non pitonico. Una volta creato l'elenco dei campi desiderati, viene utilizzato con il modulo da per leggere tutti i dati in questi campi nel cursore. Questo può quindi essere ripetuto e scritto nel file usando un'altra comprensione dell'elenco per unire tutti i campi. Questo ha il vantaggio di lavorare per qualsiasi numero di campi maggiore di 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')

Grazie @sgrieve. Ho copiato il codice che hai pubblicato e ottengo un file CSV che è quasi quello che voglio. Ma ci sono alcuni problemi. 1. Il Shapenome del campo viene ancora scritto, ma i valori Shape non lo sono. 2. Ora ci sono due nuove colonne che sono state aggiunte all'inizio della tabella spostando effettivamente le colonne a destra. Le loro colonne sembrano essere le coordinate X e Y del poligono.
Fezter

3
Ok, penso di averlo capito. Stava succedendo qualcosa nel Shapecampo, forse perché è un tipo di geometria. Quindi, ho modificato la riga in cui dichiari fieldsdi essere la seguente: fields = [f.name for f in arcpy.ListFields('FinalCadastre') if f.type <> 'Geometry'] quello ha funzionato. Non sono sicuro del perché non funzionasse senza quello però.
Fezter

2

Penso di aver riscontrato lo stesso problema e ho scoperto il motivo per cui il campo "Shape" non veniva rimosso. Quando si utilizza questo loop:

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

Ho scoperto che in realtà sta rimuovendo solo ogni altro campo. Quindi eseguirà prima il ciclo, rimuoverà 'OBJECTID', quindi il campo 'Shape' andrà al posto precedentemente detenuto da 'OBJECTID' nell'elenco, quindi passerà a quello successivo, che sarebbe quindi 'Shape_Length'.

Quindi non era specificamente la geometria Shape a impedirne la rimozione, ma solo il fatto che rimuoveva ogni altro campo quando si utilizza questo script.


Buona idea, nel qual caso la creazione di più istruzioni if ​​(non elif) potrebbe risolvere il problema.
Sleep6,

Non è una buona idea mutare un elenco in un ciclo. Puoi ottenere risultati inaspettati. Vedi questo post su un problema simile che ho avuto.
Fezter

0

Una chiave per un aspetto di questo è determinare il nome proprio per i campi non definiti dall'utente di id oggetto e geometria. Il tipo di campo della geometria è Doppio, il che non è utile in questo caso. Usando la funzione di descrizione, si può determinare il nome proprio per questi campi tra i tipi di file (es. Shapefile v file gdb, ecc; alleviare molto dolore poiché oid cambierà anche all'interno dello stesso tipo di file a volte ...).

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)]
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.