È possibile guardare il contenuto di Shapefile usando Python senza una licenza ArcMap?


40

Mi chiedevo se fosse possibile guardare il contenuto di uno shapefile usando Python senza avere la licenza ArcMap. La situazione è che è possibile creare file di forma da molte applicazioni diverse, non solo dal software ESRI. Vorrei creare uno script Python che controlla il riferimento spaziale, il tipo di funzione, i nomi e le definizioni degli attributi e il contenuto dei campi in un file di forma e li confronta con una serie di valori accettabili. Vorrei che questo script funzionasse anche se l'organizzazione non ha alcuna licenza ESRI. Per fare qualcosa del genere, devi usare ArcPy o puoi scavare in un file di forma senza usare ArcPy?


1
Dipende da quanti sforzi vuoi fare. Ci sono diverse librerie open source che ti aiuteranno (mi piace OGR secondo la risposta di Aarons) ma se vuoi davvero il controllo (e sei pronto a lavorare per esso) lo Shapefile (originariamente di Esri) è un formato aperto vedi en.wikipedia.org/wiki/Shapefile
Michael Stimson

1
I file di forma ESRI recenti (ultimi due anni) sono nascosti nel loro nuovo formato di geodatabase. Sembra che nulla possa romperli tranne il software ARCxxx. Molte agenzie pubbliche lo usano per informazioni pubbliche ... peccato.

Risposte:


34

Consiglio di familiarizzare con l' API Python GDAL / OGR per lavorare con dati vettoriali e raster. Il modo più semplice per iniziare a utilizzare GDAL / OGR è tramite una distribuzione Python come Python (x, y) , Anaconda o OSGeo4W .

Ulteriori dettagli sull'uso di GDAL per le tue attività specifiche:

Inoltre, ti consiglierei il seguente tutorial da USU per iniziare.


Prendendo in prestito dagli esempi precedenti, il seguente script utilizza gli strumenti FOSS per eseguire le seguenti azioni:

  1. Controlla il riferimento spaziale
  2. Ottieni campi e tipi di file di forma
  3. Controlla se le righe in un campo definito dall'utente contengono un valore

# Import the necessary modules
from  osgeo import ogr, osr

driver = ogr.GetDriverByName('ESRI Shapefile')
shp = driver.Open(r'C:\your\shapefile.shp')

# Get Projection from layer
layer = shp.GetLayer()
spatialRef = layer.GetSpatialRef()
print spatialRef

# Get Shapefile Fields and Types
layerDefinition = layer.GetLayerDefn()

print "Name  -  Type  Width  Precision"
for i in range(layerDefinition.GetFieldCount()):
    fieldName =  layerDefinition.GetFieldDefn(i).GetName()
    fieldTypeCode = layerDefinition.GetFieldDefn(i).GetType()
    fieldType = layerDefinition.GetFieldDefn(i).GetFieldTypeName(fieldTypeCode)
    fieldWidth = layerDefinition.GetFieldDefn(i).GetWidth()
    GetPrecision = layerDefinition.GetFieldDefn(i).GetPrecision()
    print fieldName + " - " + fieldType+ " " + str(fieldWidth) + " " + str(GetPrecision)

# Check if rows in attribute table meet some condition
inFeature = layer.GetNextFeature()
while inFeature:

    # get the cover attribute for the input feature
    cover = inFeature.GetField('cover')

    # check to see if cover == grass
    if cover == 'trees':
        print "Do some action..."

    # destroy the input feature and get a new one
    inFeature = None
    inFeature = inLayer.GetNextFeature()


Grazie per l'intuizione @MikeT. La documentazione GDAL / OGR utilizza il metodo 'Destroy ()' in tutto il loro libro di cucina. Quali problemi vedi con quel metodo?
Aaron

1
Ci sono situazioni in cui possono verificarsi segfaults quando si utilizza Destroy () ed è stato un errore di progettazione esporre questo metodo nei collegamenti. Un metodo migliore consiste nel dereferenziare gli oggetti GDAL come inFeature = None. Il ricettario GDAL / OGR non fa parte o è stato scritto dal core team GDAL / OGR.
Mike T,

@MikeT Ho modificato il post per includere i tuoi commenti - grazie.
Aaron

31

Esistono molti moduli per leggere shapefile in Python, più vecchi di ArcPy, guarda l' indice dei pacchetti Python (PyPi): shapefile . Ci sono anche molti esempi in GIS SE (cercare [Python] Fiona , per esempio)

Tutti possono leggere la geometria, i campi e le proiezioni.

Ma altri moduli come PySAL: la Python Spatial Analysis Library , Cartopy (che usano pyshp ) o Matplotlib Basemap possono anche leggere shapefile, tra le altre cose.

Il più semplice da usare è Fiona , ma se conosci solo ArcPy, usa pyshp , poiché osgeo e Fiona richiedono l' installazione della libreria GDAL C / C ++, GeoPandas necessita del modulo Pandas e PySAL è troppo grande (molti, molti altri trattamenti)

Se vuoi solo leggere il contenuto di uno shapefile, non hai bisogno di cose complesse, usa semplicemente il protocollo di interfaccia geo (GeoJSON) implementato anche in ArcPy ( ArcPy: AsShape )

Con Fiona (come dizionari Python):

import fiona
with fiona.open('a_shape.shp') as shp:
     # schema of the shapefile
     print shp.schema
     {'geometry': 'Point', 'properties': OrderedDict([(u'DIP', 'int:2'), (u'DIP_DIR', 'int:3'), (u'TYPE', 'str:10')])}
     # projection
     print shp.crs
     {u'lon_0': 4.367486666666666, u'ellps': u'intl', u'y_0': 5400088.438, u'no_defs': True, u'proj': u'lcc', u'x_0': 150000.013, u'units': u'm', u'lat_2': 49.8333339, u'lat_1': 51.16666723333333, u'lat_0': 90}
     for feature in shp:
        print feature              
{'geometry': {'type': 'Point', 'coordinates': (272070.600041, 155389.38792)}, 'type': 'Feature', 'id': '0', 'properties': OrderedDict([(u'DIP', 30), (u'DIP_DIR', 130), (u'TYPE', u'incl')])}
{'geometry': {'type': 'Point', 'coordinates': (271066.032148, 154475.631377)}, 'type': 'Feature', 'id': '1', 'properties': OrderedDict([(u'DIP', 55), (u'DIP_DIR', 145), (u'TYPE', u'incl')])}
{'geometry': {'type': 'Point', 'coordinates': (273481.498868, 153923.492988)}, 'type': 'Feature', 'id': '2', 'properties': OrderedDict([(u'DIP', 40), (u'DIP_DIR', 155), (u'TYPE', u'incl')])}

Con pyshp (come dizionari Python)

import shapefile
reader= shapefile.Reader("a_shape.shp")
# schema of the shapefile
print dict((d[0],d[1:]) for d in reader.fields[1:])
{'DIP_DIR': ['N', 3, 0], 'DIP': ['N', 2, 0], 'TYPE': ['C', 10, 0]}
fields = [field[0] for field in reader.fields[1:]]
for feature in reader.shapeRecords():
    geom = feature.shape.__geo_interface__
    atr = dict(zip(fields, feature.record))
    print geom, atr
{'type': 'Point', 'coordinates': (272070.600041, 155389.38792)} {'DIP_DIR': 130, 'DIP': 30, 'TYPE': 'incl'}
{'type': 'Point', 'coordinates': (271066.032148, 154475.631377)} {'DIP_DIR': 145, 'DIP': 55, 'TYPE': 'incl'}
{'type': 'Point', 'coordinates': (273481.498868, 153923.492988)} {'DIP_DIR': 155, 'DIP': 40, 'TYPE': 'incl'}

Con osgeo / ogr (come dizionari Python)

from osgeo import ogr
reader = ogr.Open("a_shape.shp")
layer = reader.GetLayer(0)
for i in range(layer.GetFeatureCount()):
    feature = layer.GetFeature(i)
    print feature.ExportToJson()
{"geometry": {"type": "Point", "coordinates": [272070.60004, 155389.38792]}, "type": "Feature", "properties": {"DIP_DIR": 130, "DIP": 30, "TYPE": "incl"}, "id": 0}
{"geometry": {"type": "Point", "coordinates": [271066.032148, 154475.631377]}, "type": "Feature", "properties": {"DIP_DIR": 145, "DIP": 55, "TYPE": "incl"}, "id": 1}
{"geometry": {"type": "Point", "coordinates": [273481.49887, 153923.492988]}, "type": "Feature", "properties": {"DIP_DIR": 155, "DIP": 40, "TYPE": "incl"}, "id": 2}

Con GeoPandas (come dataframe Pandas)

import geopandas as gp
shp = gp.GeoDataFrame.from_file('a_shape.shp')
print shp
        DIP_DIR    DIP  TYPE                       geometry
0         130       30  incl          POINT (272070.600041 155389.38792)
1         145       55  incl          POINT (271066.032148 154475.631377)
2         155       40  incl          POINT (273481.498868 153923.492988)

* nota su geopandas Devi usare versioni precedenti di Fiona e GDAL con esso o non si installerà. GDAL: 1.11.2 Fiona: 1.6.0 Geopandas: 0.1.0.dev-

Esistono molti tutorial sul Web e persino libri ( Python Geospatial Development , Learning Geospatial Analysis con Python e Geoprocessing con Python , in corso di stampa)

Più in generale, se vuoi usare Python senza ArcPy, guarda la semplice mappatura tematica di shapefile usando Python?


Nota che la pagina principale di Fiona diceThe kinds of data in GIS are roughly divided into rasters representing continuous scalar fields (land surface temperature or elevation, for example) and vectors representing discrete entities like roads and administrative boundaries. Fiona is concerned exclusively with the latter
Mawg,

2
Evidentemente, la domanda riguarda gli shapefile e non i raster. Sono altri moduli per file raster.
gene

Bella risposta! Qualcosa da aggiornare nel 2017?
Michael,

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.