Come aggiungere un campo attributo allo Shapefile esistente tramite Python senza ArcGIS?


24

Ho uno script Python che aggiunge un campo attributo a uno Shapefile se non esiste. Questo è facile da fare con ArcGIS (graficamente o tramite Python), ma sto cercando qualcosa che non dipende da ArcGIS.

L'ho provato senza successo con OGR, dal momento che il mio Shapefile contiene funzionalità .

Ho esaminato pyshp , ma allo stesso modo non c'è modo di modificare lo schema dopo che è stato creato. Non ho provato con shapefile (per Python) , ma non vedo pubblicizzare questa funzione. Inoltre non riesco a vedere come si possa fare armeggiando con il file DBF tramite dbfpy .

Qualcuno ha qualche idea?


Sarebbe accettabile clonare la struttura del file di forma esistente, aggiungere una nuova colonna e quindi popolarla in base al file di forma originale?
DavidF,

possibile duplicato
dell'aggiunta di

Questa domanda dovrebbe essere chiusa come duplicato di gis.stackexchange.com/q/3623/664 .
whuber

Sì, essenzialmente lo stesso. Ho guardato, ma non l'ho visto.
Mike T

Risposte:




4

Grazie a un formato piuttosto deficitario chiamato DBF, non è possibile aggiungere campi a shapefile con dati di attributo esistenti senza riscrivere o aggiungere il riempimento al DBF. Non conosco una soluzione già pronta, ma quello che vorrei fare è scrivere uno script per creare un nuovo file di forma basato su uno esistente e aggiungere i campi extra al nuovo file di forma. Quindi copia i dati di geometria / attributo dal vecchio al nuovo shapefile. E come ultimo passaggio, rimuovi il vecchio file di forma e rinomina quello nuovo. Tutto questo è abbastanza facilmente realizzato usando i collegamenti OGR in pitone.

In alternativa, puoi usare dbfpy per fare quanto sopra con solo il file DBF. L'ordine dei passaggi rimane lo stesso:

  1. Crea un nuovo DBF con struttura identica all'originale
  2. Creare nuovi campi di attributi nel nuovo DBF
  3. Copia i dati dal DBF originale al nuovo DBF
  4. Rimuovere il vecchio DBF, rinominare il nuovo DBF nel vecchio DBF

Non è necessario apportare modifiche allo shapefile (.shp) stesso o ad alcuno degli altri file, poiché non fanno riferimento alle informazioni sugli attributi contenute nel DBF. Tuttavia, è necessario mantenere l'ordine dei record esattamente lo stesso nel vecchio e nel nuovo DBF.


3

DBFpy dovrebbe funzionare per questo. Hai visto quindi esempio in questa pagina:

http://dbfpy.sourceforge.net/

Assicurati che il file di forma non sia stato modificato da nessun'altra applicazione incluso ArcGIS al momento, poiché ciò potrebbe causare problemi tramite il blocco.


Non penso che funzioni se hai già dei dati nel file DBF. L'avevo già visto prima, ma ho ricevuto un errore: "È stato aggiunto almeno un record, la struttura non può essere modificata". Hai qualche esempio specifico in mente?
Mike T

Ah, ora ricordo di sì, poiché Sasa ha affermato che sarebbe necessaria la creazione di un nuovo DBF. Copia lo schema (come nei campi, ecc.), Quindi aggiungi le tue aggiunte, quindi copia i record. Il "grande" DBF ... :(
Rob Clark,

@Mike Come è stato aggiunto un record quando tutto quello che vuoi fare è aggiungere un campo ?? L'aggiunta di un record è un errore perché rovina la connessione tra gli attributi e le forme. L'aggiunta di un campo non danneggia affatto. Qualsiasi libreria in grado di modificare i file dbf farà il lavoro correttamente.
whuber

@whuber: questo è il loro messaggio di errore. Aprire un dbf esistente con dati e vedere:from dbfpy import dbf; db = dbf.Dbf('my.dbf'); db.addField(("FOO", "C", 15))
Mike T

@Mike Grazie per aver chiarito la situazione. Sembra il risultato di una limitazione non necessaria in dbfpy :-(. Posso immaginare perché: l'aggiunta di un campo in un database non vuoto richiede che tutti i record siano letti, espansi e riscritti fisicamente. Una buona soluzione è per trovare una libreria dBase diversa o utilizzare altri software ;-).
whuber

1

Ho trovato una soluzione usando OGR e grazie all'aiuto di una domanda precedente . Ecco un esempio 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

Il mio problema era che ho usato layer_defn.AddFieldDefn(new_field)piuttosto che layer.CreateField(new_field). Mille grazie per l'aiuto e scusate per non aver verificato in modo approfondito l'altra domanda simile.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.