8

I'm splitting a large shapefile into many smaller ones using ogr. I'd like to just copy all of the field and layer config information from the original. Here's how I'm doing it now:

src = ogr.Open('original.shp', 0)
layer = src.GetLayerByIndex(0)
driver = ogr.GetDriverByName('ESRI Shapefile')
ds = driver.CreateDataSource('file1.shp')
dest_layer = ds.CreateLayer('layer1',
                            srs = layer.GetSpatialRef(),
                            geom_type=layer.GetLayerDefn().GetGeomType())
feature  = layer.GetFeature(0)
[dest_layer.CreateField(feature.GetFieldDefnRef(i)) for i in range(feature.GetFieldCount())]

Is there a more succinct way to do this?

scw
  • 16,391
  • 6
  • 64
  • 101
user2076663
  • 183
  • 1
  • 3

2 Answers2

11

Use Fiona of Sean Gillies , a very simple wrapper of the OGR library (The Fiona User Manual)

All the elements of a shapefile (schema, records) are processed using Python dictionaries:

schema of one of my shapefiles as example:

{'geometry': 'LineString', 'properties': {u'faille': 'str:20', u'type': 'str:20', u'id': 'int'}}

one record in the shapefile:

{'geometry': {'type': 'LineString', 'coordinates': [(269884.20917418826, 151805.1917153612), (270409.89083992655, 153146.21637285672), (272298.05355768028, 154047.38494269375), (272941.74539327814, 155484.96337552898), (272169.31519056071, 156117.92701386689)]}, 'id': '1', 'properties': {'faille': u'de Salinas', 'type': u'normale'}}

so to duplicate a shapefile:

from shapely.geometry import mapping, shape
import fiona
# Read the original Shapefile
with fiona.collection('original.shp', 'r') as input:
    # The output has the same schema
    schema = input.schema.copy()
    # write a new shapefile
    with fiona.collection(''file1.shp', 'w', 'ESRI Shapefile', schema) as output:
        for elem in input:
             output.write({'properties': elem['properties'],'geometry': mapping(shape(elem['geometry']))})

If you want to split a large shapefile into many smaller ones, everything takes place in the for loop but all the schemas of the original shapefile are preserved in the dictionary with schema = input.schema.copy() and {'properties': elem['properties']

see How do I find vector line bearing in QGIS or GRASS? for an example of

  1. spliting a shapefile
  2. preserve the attributes of the original shapefile in the splitted shapefile
  3. and add a new field in the splitted shapefile

For Mac OS X or Linux users, it is easy to install. For Windows users, use the version of Christoph Gohlke Unofficial Windows Binaries for Python Extension Packages

Taras
  • 32,823
  • 4
  • 66
  • 137
gene
  • 54,868
  • 3
  • 110
  • 187
  • Liked Fiona's simplicity a lot. But I ran into the problem that Fiona 1.6 does not work with GDAL 2. Hopefully they'll be upgrading that... – Akhorus Apr 25 '16 at 00:57
0

For those who struggle to install the libraries above:

import shapefile

r = shapefile.Reader('original') # original shp file
w = shapefile.Writer()

w.fields = list(r.fields)
w._shapes.extend(r.shapes()) # copy over geometry without any changes
w.save('new_shp_file')
Curtis
  • 213
  • 1
  • 7