Как добавить поле атрибута в существующий Shapefile через Python без ArcGIS?

24

У меня есть скрипт Python, который добавляет поле атрибута в Shapefile, если он не существует. Это легко сделать с ArcGIS (графически или через Python), но я ищу что-то, что не зависит от ArcGIS.

Я попытался это безуспешно с OGR, так как мой Shapefile содержит функции .

Я посмотрел на pyshp , но так же нет способа изменить схему после ее создания. Я не пробовал использовать шейп-файл (для Python) , но я не вижу эту функцию рекламируемой. Я также не могу понять, как это можно сделать, переделав файл DBF через dbfpy .

У кого-нибудь есть какие-либо идеи?

Майк Т
источник
Было бы приемлемо клонировать существующую структуру шейп-файла, добавить новый столбец, а затем заполнить его на основе исходного шейп-файла?
DavidF
Этот вопрос должен быть закрыт как дубликат gis.stackexchange.com/q/3623/664 .
whuber
Да по сути то же самое. Я посмотрел, но не увидел этого.
Майк Т

Ответы:

8

Вам следует взглянуть на эти вопросы, поскольку на них уже дан ответ: Как добавить собственные атрибуты объектов в Shapefile с помощью Python?

/programming/4215658/adding-custom-feature-attributes-to-esri-shapefile-with-python

Если вы хотите в результате только один шейп-файл, просто удалите ваши входные файлы в конце вашего скрипта.

Симо
источник
Что также похоже на gis.stackexchange.com/questions/3623/… Спасибо за то, что выкопали
Mike T
4

Благодаря довольно мертвому формату, называемому DBF, добавление полей в шейп-файлы с существующими данными атрибутов невозможно без переписывания или добавления отступов в DBF. Я не знаю готового решения, но я бы написал сценарий для создания нового шейп-файла на основе существующего и добавления дополнительных полей в новый шейп-файл. Затем скопируйте данные геометрии / атрибута из старого в новый шейп-файл. И, как последний шаг, удалите старый шейп-файл и переименуйте новый. Все это довольно легко сделать, используя привязки OGR Python.

Кроме того, вы можете использовать dbfpy, чтобы сделать выше, только с файлом DBF. Порядок шагов остается прежним:

  1. Создать новый DBF с идентичной структурой к оригиналу
  2. Создать новые поля атрибутов в новом DBF
  3. Копировать данные из исходного DBF в новый DBF
  4. Удалить старый DBF, переименовать новый DBF в старый DBF

Вам не нужно вносить какие-либо изменения в сам шейп-файл (.shp) или любые другие файлы, поскольку они не ссылаются на информацию атрибутов, содержащуюся в DBF. Однако вам необходимо сохранить порядок записей в старом и новом DBF одинаковым.

Саша Иветик
источник
3

DBFpy должен работать для этого. Вы видели пример на этой странице:

http://dbfpy.sourceforge.net/

Убедитесь, что шейп-файл не редактировался никаким другим приложением, в том числе ArcGIS, так как это может вызвать проблемы при блокировке.

Роб Кларк
источник
Я не думаю, что это работает, если у вас уже есть данные в файле DBF. Я смотрел на это раньше, но я получаю ошибку: «По крайней мере одна запись была добавлена, структура не может быть изменена». У вас есть какой-то конкретный пример?
Майк Т
Ах, я помню, теперь да, поскольку Саша сказал, что потребуется создание нового DBF. Скопируйте схему (как в полях и т. Д.), Затем внесите дополнения и скопируйте записи. "Великий" DBF ... :(
Роб Кларк
@Mike Как была добавлена ​​запись, когда все, что вы хотите сделать, это добавить поле ?? Добавление записи является ошибкой, поскольку она разрушает связь между атрибутами и фигурами. Добавление поля не приносит никакого вреда. Любая библиотека, которая может редактировать DBF-файлы, будет делать эту работу правильно.
whuber
@whuber: это их сообщение об ошибке. Откройте существующую базу данных с данными и посмотрите:from dbfpy import dbf; db = dbf.Dbf('my.dbf'); db.addField(("FOO", "C", 15))
Mike T
@ Майк Спасибо за разъяснение ситуации. Это звучит как результат ненужного ограничения в dbfpy :-(. Я могу догадаться, почему: добавление поля в непустую базу данных требует, чтобы все записи были физически прочитаны, расширены и выписаны обратно. Хорошее решение - это найти другую библиотеку dBase или использовать другое программное обеспечение ;-).
whuber
1

Я нашел решение с помощью OGR и благодаря помощи из предыдущего вопроса . Вот полный пример:

from osgeo import ogr

# Open a Shapefile, and get field names
source = ogr.Open('my.shp', update=True)
layer = source.GetLayer()
layer_defn = layer.GetLayerDefn()
field_names = [layer_defn.GetFieldDefn(i).GetName() for i in range(layer_defn.GetFieldCount())]
print len(field_names), 'MYFLD' in field_names

# Add a new field
new_field = ogr.FieldDefn('MYFLD', ogr.OFTInteger)
layer.CreateField(new_field)

# Close the Shapefile
source = None

Моя проблема была в том, что я использовал, layer_defn.AddFieldDefn(new_field)а не layer.CreateField(new_field). Большое спасибо за помощь, и я извиняюсь за то, что не проверил досконально аналогичный другой вопрос.

Майк Т
источник