Exportando apenas determinadas colunas para o arquivo CSV no ArcGIS for Desktop?

15

Eu escrevi um script python usando arcpy, que gera uma classe de recurso de polígono em um geodatabase de arquivo. Eu adicionei uma função para exportar os atributos para um arquivo CSV separado. Estou usando o código que encontrei neste post que funciona perfeitamente. No entanto, esse código exporta todas as colunas da classe de recurso. Eu só quero exportar os campos que não têm os seguintes nomes: OBJECTID, Shapeou Shape_Length.

Meu arquivo CSV é gerado com êxito e não inclui corretamente os campos OBJECTIDou Shape_Length. No entanto, o Shapecampo é gravado no arquivo. Um valor de exemplo que é gravado nesse campo é:

<geoprocessing describe geometry object object at 0x28CB90A0>

Eu adicionei uma linha para imprimir os nomes dos campos, uma vez que itera através deles e, surpreendentemente, Shapenão é impressa. É como se o ArcGIS estivesse escondendo ou dando um nome diferente.

O código para minha função está abaixo:

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

Alguém sabe o que está acontecendo aqui?


Modifiquei meu código para seguir os conselhos de @sgrieve e ele ainda estava escrevendo o Shapecampo. Se eu adicionar uma linha para imprimir os nomes dos campos conforme itera, eles listarão todos os campos, exceto o Shapecampo, e ainda assim serão gravados no CSV. Ele também adicionou as coordenadas X e Y do polígono como duas novas colunas e as colunas não estão mais alinhadas com os nomes das colunas.

Modifiquei a linha em que @sgrieve declara os campos como os seguintes:

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

O novo código funciona bem, mas ainda não tenho certeza qual era o problema. Alguém sabe o que estava acontecendo? Qual é o problema com o Shapecampo?

Fezter
fonte
Você precisa usar o Python aqui? É muito fácil ocultar os campos que você não deseja usando a guia Campos das propriedades da camada. Em seguida, na tabela de atributos abertos, exporte dados para o formato Arquivo de texto (que é CSV) para obter apenas os campos desejados.
PolyGeo
Sim, quero que isso seja adicionado ao meu script. É uma exigência do cliente.
Fezter
Alguém mais sabe o que está acontecendo aqui? Alguém sabe por que o Shapecampo estava sendo gravado no arquivo? Embora o código do @ sgrieve tenha melhorado meu código, ele não resolveu o problema.
Fezter
1
Minha abordagem para isso seria usar MakeTableView seguido por TableToTable . Se sua abordagem não chegar lá, pode haver outra maneira de "perder" seu campo Shape.
PolyGeo

Respostas:

14

Simplifiquei seu código e corrigi o erro usando o módulo da, apresentado no 10.1. Ele simplifica bastante a leitura de dados usando cursores e, em conjunto com o withcomando, esse código deve ser mais estável do que se usasse o método mais antigo de acesso a arquivos.

Ele funciona fazendo uma lista de todos os campos e removendo os campos que você não deseja da lista. Isso poderia ser feito dentro da compreensão da lista, mas seria bem confuso e não pitonico. Depois que a lista de campos desejados é criada, ela é usada com o módulo da para ler todos os dados nesses campos no cursor. Isso pode ser repetido e gravado no arquivo usando outra compreensão da lista para unir todos os campos. Isso tem o benefício de trabalhar para qualquer número de campos maior 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')
lamentar
fonte
Obrigado @sgrieve. Copiei o código que você postou e recebo um arquivo CSV que é quase o que eu quero. Mas existem alguns problemas. 1. O Shapenome do campo ainda está sendo gravado, mas os valores da forma não. 2. Agora, há duas novas colunas que foram adicionadas ao início da tabela, deslocando efetivamente as colunas para a direita. As colunas parecem ser as coordenadas X e Y do polígono.
Fezter
3
Ok, acho que resolvi. Havia algo acontecendo com o Shapecampo - talvez porque seja do tipo geometria. Então, modifiquei a linha em que você declara fieldsser o seguinte: fields = [f.name for f in arcpy.ListFields('FinalCadastre') if f.type <> 'Geometry'] esse foi o truque. Não sei por que não estava funcionando sem isso.
Fezter
2

Acho que encontrei o mesmo problema e descobri o motivo pelo qual seu campo "Shape" não estava sendo removido. Ao usar este loop:

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

Eu descobri que na verdade é apenas remover todos os outros campos. Portanto, ele primeiro percorrerá, removerá 'OBJECTID' e, em seguida, o campo 'Shape' será direcionado para o local anteriormente ocupado por 'OBJECTID' na lista, para passar para o próximo, que seria 'Shape_Length'.

Portanto, não era especificamente a geometria da forma que estava impedindo sua remoção, apenas o fato de remover todos os outros campos ao usar esse script.

Sara Flecher
fonte
Boa ideia: nesse caso, a criação de várias instruções if (não elifs) poderia resolver o problema.
precisa saber é o seguinte
Não é uma boa ideia alterar uma lista em um loop. Você pode obter resultados inesperados. Veja este post sobre um problema semelhante que tive.
Fezter
0

Uma chave para um aspecto disso é determinar o nome adequado para os campos não definidos pelo usuário de ID e geometria do objeto. O tipo do campo de geometria é Duplo, o que é inútil nesse caso. Usando a função de descrição, pode-se determinar o nome adequado para esses campos nos tipos de arquivo (por exemplo, shapefile v file gdb, etc; aliviando muita dor, pois o oid mudará mesmo no mesmo tipo de arquivo às vezes ...).

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)]
David Richey
fonte