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
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)