Vous exportez uniquement certaines colonnes vers un fichier CSV dans ArcGIS for Desktop?

15

J'ai écrit un script python en utilisant arcpy qui génère une classe d'entités polygonales dans une géodatabase fichier. J'ai ajouté une fonction pour exporter les attributs dans un fichier CSV séparé. J'utilise le code que j'ai trouvé dans cet article qui fonctionne parfaitement. Cependant, ce code exporte chaque colonne de la classe d'entités. Je veux seulement exporter les champs qui ne sont pas les noms suivants: OBJECTID, Shapeou Shape_Length.

Mon fichier CSV est correctement généré et il n'inclut pas correctement les champs OBJECTIDou Shape_Length. Cependant, le Shapechamp est écrit dans le fichier. Un exemple de valeur qui est écrit dans ce champ est:

<geoprocessing describe geometry object object at 0x28CB90A0>

J'ai ajouté une ligne pour imprimer les noms de champs au fur et à mesure de leur itération et, étonnamment, Shapen'est pas imprimé. C'est comme si ArcGIS le cache ou lui donne un nom différent.

Le code de ma fonction est ci-dessous:

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

Est-ce que quelqu'un sait ce qui se passe ici?


J'ai modifié mon code pour suivre les conseils de @sgrieve et il écrivait toujours le Shapechamp. Si j'ajoute une ligne pour imprimer les noms de champs au fur et à mesure qu'ils les parcourent, il répertorie tous les champs sauf le Shapechamp, mais il écrit toujours dans le CSV. Il a également ajouté les coordonnées X et Y du polygone en tant que deux nouvelles colonnes et les colonnes ne sont plus alignées avec les noms des colonnes.

J'ai modifié la ligne où @sgrieve déclare que les champs sont les suivants:

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

Le nouveau code fonctionne bien, mais je ne sais toujours pas quel était le problème. Quelqu'un sait-il ce qui se passait? Quel est le problème avec le Shapedomaine?

Fezter
la source
Avez-vous besoin d'utiliser Python ici? Il est très facile de masquer les champs dont vous ne voulez pas en utilisant l'onglet Champs des propriétés du calque. Ensuite, à partir de la table d'attributs ouverte Exportez les données au format de fichier texte (qui est au format CSV) pour obtenir uniquement les champs que vous souhaitez.
PolyGeo
Oui, je veux que cela soit ajouté à mon script. C'est une exigence du client.
Fezter
Quelqu'un d'autre sait-il ce qui se passe ici? Est-ce que quelqu'un sait pourquoi le Shapechamp était écrit dans le fichier? Bien que le code de @ sgrieve ait probablement amélioré mon code, il n'a pas résolu le problème.
Fezter
1
Mon approche serait d'utiliser MakeTableView suivi de TableToTable . Si votre approche n'y arrive pas, cela pourrait être une autre façon de "perdre" votre champ Shape.
PolyGeo

Réponses:

14

J'ai simplifié votre code et corrigé l'erreur en utilisant le module da introduit dans 10.1. Il rationalise considérablement la lecture des données à l'aide de curseurs et, utilisé avec la withcommande, ce code devrait être plus stable que s'il utilisait l'ancienne méthode d'accès aux fichiers.

Cela fonctionne en faisant une liste de tous les champs puis en supprimant les champs que vous ne voulez pas de la liste. Cela pourrait être fait dans la compréhension de la liste, mais ce serait assez désordonné et non pythonique. Une fois que la liste des champs souhaités a été créée, elle est utilisée avec le module da pour lire toutes les données de ces champs dans le curseur. Cela peut ensuite être bouclé et écrit dans le fichier en utilisant une autre compréhension de liste pour joindre tous les champs. Cela a l'avantage de travailler pour n'importe quel nombre de champs supérieur à 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')
sgrieve
la source
Merci @sgrieve. J'ai copié le code que vous avez publié et j'obtiens un fichier CSV qui correspond presque à ce que je veux. Mais il y a quelques problèmes. 1. Le Shapenom du champ est toujours en cours d'écriture mais les valeurs de forme ne le sont pas. 2. Il y a maintenant deux nouvelles colonnes qui ont été ajoutées au début du tableau en déplaçant efficacement les colonnes vers la droite. Ces colonnes semblent être les coordonnées X et Y du polygone.
Fezter
3
Ok, je pense que je l'ai résolu. Il se passait quelque chose avec le Shapechamp - peut-être parce que c'est un type de géométrie. J'ai donc modifié la ligne où vous déclarez fieldsêtre la suivante: fields = [f.name for f in arcpy.ListFields('FinalCadastre') if f.type <> 'Geometry'] cela a fait l'affaire. Je ne sais pas pourquoi cela ne fonctionnait pas sans cela.
Fezter
2

Je pense avoir rencontré le même problème et découvert la raison pour laquelle votre champ "Forme" n'était pas supprimé. Lors de l'utilisation de cette boucle:

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

J'ai découvert qu'il ne supprimait en fait que tous les autres champs. Il va donc d'abord parcourir, supprimer `` OBJECTID '', puis le champ `` Forme '' ira à l'emplacement tenu précédemment par `` OBJECTID '' dans la liste, donc il passera au suivant, qui serait alors `` Longueur_Forme ''.

Ce n'était donc pas spécifiquement la géométrie de la forme qui l'empêchait d'être supprimée, juste le fait qu'il supprime tous les autres champs lors de l'utilisation de ce script.

Sara Flecher
la source
Bonne idée, auquel cas la création de plusieurs instructions if (et non elifs) pourrait résoudre le problème.
Sleep6
Ce n'est pas une bonne idée de muter une liste en boucle. Vous pouvez obtenir des résultats inattendus. Voir ce post sur un problème similaire que j'ai eu.
Fezter
0

Un élément clé de cet aspect consiste à déterminer le nom approprié pour les champs non définis par l'utilisateur de l'ID d'objet et de la géométrie. Le type du champ de géométrie est Double, ce qui n'est pas utile dans ce cas. En utilisant la fonction de description, on peut déterminer le nom correct de ces champs à travers les types de fichiers (c'est-à-dire shapefile v file gdb, etc.; atténuer beaucoup de problèmes car oid changera même parfois dans le même type de fichier ...).

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
la source