Mengekspor hanya kolom tertentu ke file CSV di ArcGIS untuk Desktop?

15

Saya telah menulis skrip python menggunakan arcpy yang menampilkan kelas fitur poligon menjadi File Geodatabase. Saya telah menambahkan fungsi untuk mengekspor atribut ke file CSV yang terpisah. Saya menggunakan kode yang saya temukan di posting ini yang berfungsi dengan baik. Namun, kode itu mengekspor setiap kolom di kelas fitur. Saya hanya ingin mengekspor bidang yang tidak memiliki nama berikut: OBJECTID, Shape, atau Shape_Length.

File CSV saya berhasil dibuat, dan dengan benar tidak menyertakan bidang OBJECTIDatau Shape_Length. Namun, Shapebidang ini ditulis ke file. Nilai contoh yang ditulis untuk bidang itu adalah:

<geoprocessing describe geometry object object at 0x28CB90A0>

Saya telah menambahkan baris untuk mencetak nama-nama bidang karena berulang melalui mereka dan secara mengejutkan, Shapetidak dicetak. Seolah-olah ArcGIS menyembunyikannya atau memberinya nama yang berbeda.

Kode untuk fungsi saya di bawah:

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

Adakah yang tahu apa yang terjadi di sini?


Saya memodifikasi kode saya untuk mengikuti saran dari @sgrieve dan masih menulis kolom Shape. Jika saya menambahkan baris untuk mencetak nama field sebagai iterates melalui mereka, itu daftar semua bidang kecuali dalam Shapelapangan, namun masih menulis ke CSV tersebut. Itu juga menambahkan koordinat X dan Y dari poligon sebagai dua kolom baru dan kolom tidak lagi selaras dengan nama kolom.

Saya telah memodifikasi baris tempat @sgrieve menyatakan bidang sebagai berikut:

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

Kode baru berfungsi dengan baik, tapi saya masih tidak yakin apa masalahnya. Adakah yang tahu apa yang sedang terjadi? Apa masalahnya dengan Shapebidang itu?

Fezter
sumber
Apakah Anda perlu menggunakan Python di sini? Sangat mudah untuk menyembunyikan bidang yang tidak Anda inginkan menggunakan tab Bidang dari lapisan properti. Kemudian dari tabel atribut terbuka Ekspor data ke File Teks (yang merupakan CSV) format untuk mendapatkan hanya bidang yang Anda inginkan.
PolyGeo
Ya, saya ingin ini ditambahkan ke skrip saya. Ini persyaratan klien.
Fezter
Adakah yang tahu apa yang sedang terjadi di sini? Apakah ada yang tahu mengapa Shapebidang ini ditulis ke file? Sementara kode @ sgrieve mungkin memperbaiki kode saya, itu tidak menyelesaikan masalah.
Fezter
1
Pendekatan saya untuk ini adalah dengan menggunakan MakeTableView diikuti oleh TableToTable . Jika pendekatan Anda tidak sampai di sana, ini mungkin cara lain untuk "kehilangan" bidang Bentuk Anda.
PolyGeo

Jawaban:

14

Saya telah menyederhanakan kode Anda dan memperbaiki kesalahan dengan menggunakan modul da yang diperkenalkan pada 10.1. Ini sangat merampingkan pembacaan data menggunakan kursor, dan digunakan bersama dengan withperintah kode ini harus lebih stabil daripada jika menggunakan metode akses file yang lebih lama.

Ini bekerja dengan membuat daftar semua bidang dan kemudian menghapus bidang yang tidak Anda inginkan dari daftar. Ini bisa dilakukan dalam pemahaman daftar, tetapi itu akan sangat berantakan dan tidak pythonic. Setelah daftar bidang yang diinginkan telah dibuat, ia digunakan dengan modul da untuk membaca semua data dalam bidang ini ke dalam kursor. Ini kemudian dapat diulang dan ditulis ke file menggunakan pemahaman daftar lain untuk bergabung dengan semua bidang. Ini memiliki manfaat bekerja untuk sejumlah bidang yang lebih besar dari 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
sumber
Terima kasih @sgrieve. Saya menyalin kode yang Anda poskan dan saya mendapatkan file CSV yang hampir saya inginkan. Tetapi ada beberapa masalah. 1. Nama Shapebidang masih ditulis tetapi nilai Shape tidak. 2. Sekarang ada dua kolom baru yang telah ditambahkan ke awal tabel secara efektif menggeser kolom ke kanan. Kolomnya tampak sebagai koordinat X dan Y dari poligon.
Fezter
3
Ok, saya pikir saya sudah berhasil. Ada sesuatu yang terjadi pada Shapebidang - mungkin karena ini adalah tipe geometri. Jadi, saya telah memodifikasi baris tempat Anda menyatakan fieldssebagai berikut: fields = [f.name for f in arcpy.ListFields('FinalCadastre') if f.type <> 'Geometry'] yang melakukan trik. Tidak yakin mengapa itu tidak berhasil tanpanya.
Fezter
2

Saya pikir saya mengalami masalah yang sama dan menemukan alasan mengapa bidang Anda "Bentuk" tidak dihapus. Saat menggunakan loop ini:

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

Saya telah menemukan bahwa sebenarnya hanya menghapus setiap bidang lainnya. Jadi pertama-tama akan melalui, menghapus 'OBJECTID', dan kemudian bidang 'Bentuk' pergi ke tempat yang sebelumnya dimiliki oleh 'OBJECTID' dalam daftar, sehingga bergerak ke yang berikutnya, yang kemudian akan menjadi 'Shape_Length'.

Jadi bukan geometri Shape yang mencegahnya dihapus, hanya fakta bahwa itu menghilangkan setiap bidang lain saat menggunakan skrip ini.

Sara Flecher
sumber
Ide bagus, dalam hal ini membuat beberapa jika pernyataan (bukan elif) dapat menyelesaikan masalah.
Sleep6
Bukan ide yang baik untuk mengubah daftar dalam satu lingkaran. Anda bisa mendapatkan hasil yang tidak terduga. Lihat posting ini pada masalah serupa yang saya miliki.
Fezter
0

Kunci untuk satu aspek dari ini adalah menentukan nama yang tepat untuk bidang id objek dan geometri yang tidak ditentukan pengguna. Jenis bidang geometri adalah Ganda, yang tidak membantu dalam kasus ini. Dengan menggunakan fungsi uraikan, seseorang dapat menentukan nama yang tepat untuk bidang-bidang ini di seluruh tipe file (mis. Shapefile v file gdb, dll; mengurangi banyak kesedihan karena oid akan berubah bahkan dalam tipe file yang sama di waktu ...).

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
sumber