I use GDAL in Python for importing shapefile. I want to know the field names for the file, my current way is:
fields = []
for i in range(1, layer.GetFeature(0).GetFieldCount()):
field = layer.GetFeature(0).GetDefnRef().GetFieldDefn(i).GetName()
fields.append(field)
But this way, I am getting the feature for the first layer. Does it mean it is possible that different layers can have different features?
If not, is it possible to get the field names at once, instead of getting into this deep? If yes, is there any easier way of getting the field names?
Answer
1) individual shapefile: as in the comment, a shapefile has only one layer. If you want only the names of the fields
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']
You can use the GeoJSON format with a Python generator (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']
This introduces Fiona (another Python wrapper of OGR, Python 2.7.x and 3.x). All results are Python dictionaries (GeoJSON format).
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)])}
And GeoPandas (Fiona + pandas, Python 2.7.x and 3.x). The result is a 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)
2) Multiple shapefiles: if you want to iterate through multiple shapefiles in a folder
With 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
or with a generator
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()
With 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()
No comments:
Post a Comment