Экспорт только определенных столбцов в файл CSV в ArcGIS for Desktop?

15

Я написал скрипт на python с использованием arcpy, который выводит класс пространственных объектов многоугольника в базу геоданных файлов. Я добавил функцию для экспорта атрибутов в отдельный файл CSV. Я использую код, который я нашел в этом посте, который отлично работает. Однако этот код экспортирует каждый столбец в классе объектов. Я только хочу , чтобы экспортировать поля , которые не имеют следующие названия: OBJECTID, Shapeили Shape_Length.

Мой файл CSV генерируется успешно, и он правильно не включает поля OBJECTIDили Shape_Length. Тем не менее, Shapeполе будет записано в файл. Пример значения, которое записывается в это поле:

<geoprocessing describe geometry object object at 0x28CB90A0>

Я добавил строку для печати имен полей, так как они проходят через них и, Shapeкак ни странно, не печатаются. Как будто ArcGIS скрывает его или дает другое имя.

Код для моей функции ниже:

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

Кто-нибудь знает, что здесь происходит?


Я изменил свой код, следуя совету @sgrieve, и он все еще писал Shapeполе. Если добавить строку , чтобы напечатать имена полей , как он перебирает через них, в нем перечислены все поля , за исключением в Shapeполе, но он до сих пор пишет в CSV. Также добавлены координаты X и Y многоугольника в виде двух новых столбцов, и столбцы больше не выровнены с именами столбцов.

Я изменил строку, где @sgrieve объявляет следующие поля:

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

Новый код работает нормально, но я все еще не уверен, в чем проблема. Кто-нибудь знает, что происходит? Что за дело с Shapeполем?

Фезтер
источник
Вам нужно использовать Python здесь? Очень легко скрыть ненужные поля, используя вкладку «Поля» в свойствах слоя. Затем из открытой таблицы атрибутов экспортируйте данные в текстовый файл (формат CSV), чтобы получить только те поля, которые вам нужны.
PolyGeo
Да, я хочу, чтобы это было добавлено в мой сценарий. Это требование клиента.
Фезтер
Кто-нибудь еще знает, что здесь происходит? Кто-нибудь знает, почему Shapeполе было записано в файл? Хотя код @ sgrieve, возможно, улучшил мой код, он не решил проблему.
Фезтер
1
Мой подход к этому будет использовать MakeTableView, а затем TableToTable . Если ваш подход не подходит, это может быть еще один способ «потерять» поле формы.
PolyGeo

Ответы:

14

Я упростил ваш код и исправил ошибку, используя модуль da, представленный в 10.1. Он значительно упрощает чтение данных с помощью курсоров и используется вместе с withкомандой, этот код должен быть более стабильным, чем если бы использовался более старый метод доступа к файлам.

Он работает, составляя список всех полей, а затем удаляя ненужные поля из списка. Это можно сделать в рамках понимания списка, но это будет довольно грязно и непитонно. После создания списка требуемых полей он используется с модулем da для считывания всех данных в этих полях в курсор. Затем это можно перебрать и записать в файл, используя другое понимание списка, чтобы объединить все поля. Преимущество работы с любым числом полей больше 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
источник
Спасибо @sgrieve. Я скопировал код, который вы разместили, и я получил файл CSV, который почти то, что я хочу. Но есть несколько вопросов. 1. Имя Shapeполя все еще записывается, а значения Shape - нет. 2. Теперь есть два новых столбца, которые были добавлены в начало таблицы, эффективно смещая столбцы вправо. Их столбцы являются координатами X и Y многоугольника.
Фезтер
3
Хорошо, я думаю, что я решил это. Что-то происходило с Shapeполем - возможно, потому что это тип геометрии. Итак, я изменил строку, где вы объявляете fieldsследующее: fields = [f.name for f in arcpy.ListFields('FinalCadastre') if f.type <> 'Geometry'] это сработало. Не уверен, почему без этого не получилось.
Фезтер
2

Я думаю, что столкнулся с той же проблемой и обнаружил причину, по которой ваше поле "Форма" не было удалено. При использовании этого цикла:

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

Я обнаружил, что на самом деле это только удаление всех остальных полей. Таким образом, он сначала перебирает, удаляет «OBJECTID», а затем поле «Shape» переходит в место, которое ранее занимал «OBJECTID» в списке, поэтому оно переходит к следующему, которое затем будет «Shape_Length».

Так что не именно геометрия Shape препятствовала его удалению, а лишь тот факт, что она удаляет все остальные поля при использовании этого скрипта.

Сара Флехер
источник
Хорошая идея, в этом случае создание нескольких операторов if (не elifs) может решить проблему.
Sleep6
Это не хорошая идея, чтобы изменить список в цикле. Вы можете получить неожиданные результаты. Смотрите этот пост по аналогичной проблеме, которую я имел.
Фезтер
0

Ключом к одному аспекту этого является определение правильного имени для не определенных пользователем полей идентификатора объекта и геометрии. Тип геометрического поля - Double, что в данном случае бесполезно. Используя функцию description, можно определить правильное имя для этих полей в разных типах файлов (например, shapefile v file gdb и т. Д .; устранение большого горя, поскольку oid будет меняться даже в пределах одного и того же типа файла ...).

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)]
Дэвид Ричи
источник