Search code examples
pythonshapefilepyshp

Remove a record from shapefile with python


I have an ESRI shapefile .shp (with all associated files like .shx, .dbf and many more) which I want to edit - I need to remove the first record and save the file.

For this purpose I installed pyshp and tried to parse and edit the shapefile. This is what I have tried:

import shapefile
e = shapefile.Editor('location/of/my/shp')
e.shapes()
# example output
>>> [<shapefile._Shape instance at 0x7fc5e18d93f8>,
     <shapefile._Shape instance at 0x7fc5e18d9440>,
     <shapefile._Shape instance at 0x7fc5e18d9488>,
     <shapefile._Shape instance at 0x7fc5e18d94d0>,
     <shapefile._Shape instance at 0x7fc5e18d9518>]

From here I want to delete the first entry <shapefile._Shape instance at 0x7fc5e18d93f8> and then save the file:

e.delete(0) # I tried e.delete(shape=0) too
e.save()

However the record is still available in the newly saved file.

Unfortunately the documentation doesn't go in depth about these things.

How can I accomplish my goal? How to check that the deletion has been successful before saving the file?


Solution

  • I'm not familiarized with pyshp but this can be easily solved using ogr, which allows to work with vector data and makes part of the gdal library.

    from osgeo import ogr
    
    fn = r"file.shp"  # The path of your shapefile
    ds = ogr.Open(fn, True)  # True allows to edit the shapefile
    lyr = ds.GetLayer()
    
    print("Features before: {}".format(lyr.GetFeatureCount()))
    lyr.DeleteFeature(0)  # Deletes the first feature in the Layer
    
    # Repack and recompute extent
    # This is not mandatory but it organizes the FID's (so they start at 0 again and not 1)
    # and recalculates the spatial extent.
    ds.ExecuteSQL('REPACK ' + lyr.GetName())
    ds.ExecuteSQL('RECOMPUTE EXTENT ON ' + lyr.GetName())
    
    print("Features after: {}".format(lyr.GetFeatureCount()))
    
    del ds