3

I would like to open some shapefile with shapefile.Reader but I would like to see some part of it, for example 10000-20000 records. How to set up a section? I can't find that in documentation.

with shapefile.Reader(shapefile_path) as shp:
1
  • Shapefile is direct-access capable (through .shx). Most drivers should support direct access. But it's trivial to just add a counter and continue until the record arrives, then break when you're done. – Vince May 6 at 0:50
5

shapefile.Reader doesn't support indexing. It loads all data to the memory. After using shapefile.Reader("file_path") you can get a specific range of features in different ways.

  1. Using itertools as in Thomas's answer.

    import shapefile
    import itertools
    
    shapefile_path = "C:/path/to/shapefile.shp"
    shp = shapefile.Reader(shapefile_path)
    
    section = [s for s in  itertools.islice(shp, 10000, 20000)]  
    
  2. Using your own method that uses iterShapeRecords method which returns a generator.

    import shapefile
    
    shapefile_path = "C:/path/to/shapefile.shp"
    shp = shapefile.Reader(shapefile_path)
    
    def slice(shp, start, end):    
        section = []
        for i, row in enumerate(shp.iterShapeRecords()):
            if start <= i < end:
                section.append(row)
            elif i > end:
                break
        return section
    
    section = slice(shp, 10000, 20000)
    
  3. Using shapeRecords method which returns a list, then, you can slice it.

    import shapefile
    
    shapefile_path = "C:/path/to/shapefile.shp"
    shp = shapefile.Reader(shapefile_path)
    
    section = shp.shapeRecords()[10000:20000]
    

(1) and (2) have almost the same performance. (3) has low performance for a big dataset but is easy to use for a small one.

4

You can use Python itertools for this purpose

import json
import itertools
import shapefile


with shapefile.Reader("ne_10m_admin_0_countries.shp") as shp: 
     # print(shp.fields) # Fields info
     # print(len(shp)) # To count to help decide range
     features = []
     for s in itertools.islice(shp, 10000, 20000): # Loop only on a subset of features
     # for s in shp: # Swap code comment with above line to loop on all features
          features.append({
              "type": "Feature",
              "geometry": s.shape.__geo_interface__,
              "properties": s.record.as_dict()
          })

# Write to GeoJSON file
with open('demo.geojson', 'w') as outfile:
    json.dump({"type": "FeatureCollection", "features": features}, outfile)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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