Obtener nombres de campo de archivos de forma usando GDAL

15

Yo uso GDAL en Python para importar shapefile. Quiero saber los nombres de campo para el archivo, mi forma actual es:

fields = []
for i in range(1, layer.GetFeature(0).GetFieldCount()):
    field = layer.GetFeature(0).GetDefnRef().GetFieldDefn(i).GetName()
    fields.append(field)

Pero de esta manera, obtengo la función para la primera capa. ¿Significa que es posible que diferentes capas puedan tener diferentes características?

Si no, ¿es posible obtener los nombres de los campos a la vez, en lugar de profundizar tanto? En caso afirmativo, ¿hay alguna forma más fácil de obtener los nombres de campo?

usuario3716774
fuente
Shapefile siempre tiene solo una capa. También creo que cada característica tiene los mismos atributos, por lo que es suficiente verificar solo la primera característica.
user30184

Respuestas:

24

1) archivo de forma individual: como en el comentario, un archivo de forma tiene solo una capa. Si solo quieres los nombres de los campos

from osgeo import ogr
source = ogr.Open("a_shapefile.shp")
layer = source.GetLayer()
schema = []
ldefn = layer.GetLayerDefn()
for n in range(ldefn.GetFieldCount()):
    fdefn = ldefn.GetFieldDefn(n)
    schema.append(fdefn.name)
print schema
['dip_dir', 'dip', 'cosa', 'sina']

Puede usar el formato GeoJSON con un generador de Python ( ogr_geointerface.py )

def records(layer):  
    # generator 
    for i in range(layer.GetFeatureCount()):
        feature = layer.GetFeature(i)
        yield json.loads(feature.ExportToJson())
features = record(layer)
first_feat = features.next()
print first_feat
{u'geometry': {u'type': u'Point', u'coordinates': [272070.600041, 155389.38792]}, u'type': u'Feature', u'properties': {u'dip_dir': 130, u'dip': 30, u'cosa': -0.6428, u'sina': -0.6428}, u'id': 0}
print first_feat['properties'].keys()
[u'dip', u'dip_dir', u'cosa', u'sina']

Esto presenta Fiona (otro contenedor Python de OGR, Python 2.7.xy 3.x). Todos los resultados son diccionarios de Python (formato GeoJSON).

import fiona
shapes = fiona.open("a_shapefile.shp")
shapes.schema
{'geometry': 'Point', 'properties': OrderedDict([(u'dip_dir', 'int:3'), (u'dip', 'int:2'), (u'cosa', 'float:11.4'), (u'sina', 'float:11.4')])}
shapes.schema['properties'].keys()
[u'dip', u'dip_dir', u'cosa', u'sina']
# first feature
shapes.next()
{'geometry': {'type': 'Point', 'coordinates': (272070.600041, 155389.38792)}, 'type': 'Feature', 'id': '0', 'properties': OrderedDict([(u'dip_dir', 130), (u'dip', 30), (u'cosa', -0.6428), (u'sina', -0.6428)])}

Y GeoPandas (Fiona + pandas , Python 2.7.xy 3.x). El resultado es un Pandas DataFrame (= GeoDataFrame).

import geopandas as gpd
shapes = gpd.read_file("a_shapefile.shp")
list(shapes.columns.values)
[u'dip', u'dip_dir', u'cosa', u'sina', 'geometry']
# first features
shapes.head(3)

ingrese la descripción de la imagen aquí

2) Múltiples archivos de forma: si desea recorrer múltiples archivos de forma en una carpeta

Con osgeo.ogr

for subdir, dirs, files in os.walk(rootdir):
     for file in files:
        if file.endswith(".shp"):
           source = ogr.Open(os.path.join(rootdir, file))
           layer = source.GetLayer()
           ldefn = layer.GetLayerDefn()
           schema = [ldefn.GetFieldDefn(n).name  for n in range(ldefn.GetFieldCount())]
           print schema

o con un generador

def records(shapefile):  
    # generator 
    reader = ogr.Open(shapefile)
    layer = reader.GetLayer(0)
    for i in range(layer.GetFeatureCount()):
        feature = layer.GetFeature(i)
        yield json.loads(feature.ExportToJson())

for subdir, dirs, files in os.walk(rootdir):
    for file in files:
       if file.endswith(".shp"):
          layer = records(os.path.join(rootdir, file))
          print layer.next()['properties'].keys()

Con fiona

import fiona
for subdir, dirs, files in os.walk(rootdir):
   for file in files:
      if file.endswith(".shp"):
          layer = fiona.open(os.path.join(rootdir, file))
          print layer.schema['properties'].keys()
gene
fuente
1
¡Esta es una respuesta excelentemente exhaustiva!
Kersten
11

Utilizar:

from osgeo import ogr

ds = ogr.Open("file.shp")
lyr = ds.GetLayer()

field_names = [field.name for field in lyr.schema]
print(field_names)
Marcelo Villa
fuente
Perfecto. Eso es todo lo que se requiere
Ishan Tomar