¿Cómo agregar un campo de atributo a Shapefile existente a través de Python sin ArcGIS?

24

Tengo un script de Python que agrega un campo de atributo a un Shapefile si no existe. Esto es fácil de hacer con ArcGIS (gráficamente o vía Python), pero estoy buscando algo que no dependa de ArcGIS.

Intenté esto sin éxito con OGR, ya que mi Shapefile contiene características .

He visto pyshp , pero de manera similar no hay forma de modificar el esquema después de que se haya creado. No he probado con shapefile (para Python) , pero no veo esta característica anunciada. Tampoco puedo ver cómo esto se puede hacer jugando con el archivo DBF a través de dbfpy .

¿Alguien tiene alguna idea?

Mike T
fuente
¿Sería aceptable clonar la estructura del archivo de forma existente, agregar una nueva columna y luego completarla en función del archivo de forma original?
DavidF
posible duplicado de Agregar atributos de
funciones
Esta pregunta debe cerrarse como un duplicado de gis.stackexchange.com/q/3623/664 .
whuber
Sí, esencialmente lo mismo. Lo miré, pero no lo vi.
Mike T

Respuestas:

4

Gracias a un formato bastante cerebral llamado DBF, no es posible agregar campos a los archivos de forma con datos de atributos existentes sin reescribir o agregar relleno al DBF. No conozco una solución preparada, pero lo que haría sería escribir un script para crear un nuevo archivo de forma basado en uno existente y agregar los campos adicionales al nuevo archivo de forma. Luego copie los datos de geometría / atributo del archivo de forma antiguo al nuevo. Y como paso final, elimine el antiguo archivo de forma y cambie el nombre del nuevo. Todo esto se logra con bastante facilidad utilizando los enlaces de Python de OGR.

Alternativamente, puede usar dbfpy para hacer lo anterior solo con el archivo DBF. El orden de los pasos sigue siendo el mismo:

  1. Cree un nuevo DBF con estructura idéntica a la original
  2. Crear nuevos campos de atributos en el nuevo DBF
  3. Copie datos del DBF original al nuevo DBF
  4. Elimine DBF antiguo, cambie el nombre de DBF nuevo a DBF antiguo

No es necesario realizar ningún cambio en el archivo de forma (.shp) ni en ninguno de los otros archivos, ya que no hacen referencia a la información de atributos contenida en el DBF. Sin embargo, debe mantener el orden de los registros exactamente igual en el DBF antiguo y en el nuevo.

Sasa Ivetic
fuente
3

DBFpy debería funcionar para esto. ¿Has visto el ejemplo en esta página?

http://dbfpy.sourceforge.net/

Asegúrese de que el archivo de forma no esté siendo editado por ninguna otra aplicación, incluida ArcGIS en ese momento, ya que esto puede causar problemas al bloquear.

Rob Clark
fuente
No creo que esto funcione si ya tienes datos en el archivo DBF. Lo había visto antes, pero aparece un error: "Se agregó al menos un registro, la estructura no se puede cambiar". ¿Tienes algún ejemplo específico en mente?
Mike T
Ah, ahora recuerdo que sí, ya que Sasa dijo que se requeriría la creación de un nuevo DBF. Copie el esquema (como en los campos, etc.) y luego realice sus adiciones, luego copie los registros. El "gran" DBF ... :(
Rob Clark
@ Mike ¿Cómo se agregó un registro cuando todo lo que quieres hacer es agregar un campo ? Agregar un registro es un error porque arruina la conexión entre los atributos y las formas. Agregar un campo no hace daño en absoluto. Cualquier biblioteca que pueda editar archivos dbf hará el trabajo correctamente.
whuber
@whuber: Ese es su mensaje de error. Abra un dbf existente que tenga datos y vea:from dbfpy import dbf; db = dbf.Dbf('my.dbf'); db.addField(("FOO", "C", 15))
Mike T
@ Mike Gracias por aclarar la situación. Eso suena como el resultado de una limitación innecesaria en dbfpy :-(. Puedo adivinar por qué: agregar un campo en una base de datos no vacía requiere que todos los registros se lean, expandan y vuelvan a escribir físicamente. Una buena solución es para encontrar una biblioteca de dBase diferente o usar otro software ;-).
whuber
1

Encontré una solución usando OGR y gracias a la ayuda de una pregunta anterior . Aquí hay un ejemplo completo:

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

Mi problema fue que usé en layer_defn.AddFieldDefn(new_field)lugar de layer.CreateField(new_field). Muchas gracias a la ayuda, y lo siento por no haber verificado la otra pregunta similar.

Mike T
fuente