0

I need to be able to select one feature/record at a time within a polygon shapefile, regardless of how many shapes it contains, using open source python libraries (e.g., OGR, pyshp, fiona). Then I want to use each feature/record in a different function that requires a shapefile format. Below is what I'm attempting with pyshp:

shp = shapefile.Reader(file)  ## open and read the shapefile
shp = shp.shapes()  ## read the geometry information of each shape record
shpInPoly = []  ## empty array that will contain the features in the file
for i in shp:
   shpInPoly.append(i)

Then I'd assume I could grab the first feature in the array of appended features like this:

currentPolygon = shpInPoly[0]

And use the "currentPolygon" variable in my other function with the first record/feature in the original shapefile.

But it doesn't work. The error I get in my other function which requires shapefile inputs is "shapefile.ShapefileException: Shapefile Reader requires a shapefile or file-like object." The other alternative, per the question title (and what I'm thinking is likely best), would be to export that selected feature/record and all its content (geometry and fields) to a new shapefile, to achieve the same purpose of using that in another shapefile-requring function. The only posts I found that attempt something similar are Exporting Selected Feature to New Shapefile using ArcPy? and Splitting shapefile into many shapefiles with open source?, but I can't use ArcPy.

Any ideas?

1 Answer 1

3

If your other function expects a single shapefile input, then you need to split each polygon in the polygon shapefile into its own shapefile. Right now you are passing subsections of a shapefile and the other function is complaining. The code will look something like the following.

import shapefile

# path and name of the input shapefile
input_shp = "my_polys.shp"

# read the input shapefile
r = shapefile.Reader(input_shp)

# list of filenames for the split 
# polygon shapefiles
shp_files = []

# Loop through each polygon and dbf record,
# and create a new shapefile. We add an
# enumeration to give us a number for each
# new shapefile name.
for i, shapeRec in enumerate(r.iterShapeRecords()):
    # polygon
    shape = shapeRec.shape
    # dbf record
    rec = shapeRec.record
    # Create a new shapefile writer
    w = shapefile.Writer(shapefile.POLYGON)
    # Copy the dbf fields from the original shapefile
    w.fields = list(r.fields)
    # Add the polygon to the new shapefiles list of shapes
    w._shapes.append(shape)
    # Do the same for the dbf record
    w.records.append(rec)
    # Create a unique name for each shapefle
    # based on the enumeration index
    shp_name = "poly_{}.shp".format(i)
    # Save the shapefile and append the 
    # name to a list of names
    w.save(shp_name)
    shp_files.append(shp_name)

# Now you can loop through the list
# of shapefile names and pass them
# to the other function
for shp in shp_files:
    my_other_function(shp)

# Or if the other function expects
# a pyshp shapefile object:
for shp in shp_files:
    r = shapefile.Reader(shp)
    my_other_function(r)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.