0

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?

cezar
  • 11,616
  • 6
  • 48
  • 84
  • Can the downvoter please explain the reason for downvoting? – cezar Jan 15 '18 at 16:36
  • 1
    been having the same issue. what I found is that the shape is actually deleted, but the accompanying .dbf file doesn't change. my dataframe has half a dozen columns. – Randall Stevens Oct 11 '18 at 01:44
  • @RandallStevens Thanks for the comment. I'll check the thing with the '.dbf' file next time I come back to this problem. – cezar Oct 11 '18 at 06:13

2 Answers2

2

Following exactly the procedure you have described seems to work just fine for me. I start by opening a shapefile:

>>> e = shapefile.Editor('example')

This file has three shapes:

>>> e.shapes()
[<shapefile._Shape instance at 0x7f6cb5f67dd0>, <shapefile._Shape instance at 0x7f6cb5f67f38>, <shapefile._Shape instance at 0x7f6cb5f6e050>]

I delete the first shape and save the file:

>>> e.delete(0)
>>> e.save('example')

Now I re-open the file:

>>> e = shapefile.Editor('example')

And I can see that it now has only two shapes:

>>> e.shapes()
[<shapefile._Shape instance at 0x7f6cb5f6e518>, <shapefile._Shape instance at 0x7f6cb5f6e560>]
larsks
  • 277,717
  • 41
  • 399
  • 399
  • Thank you for your answer. The approach looks very clean, but I have no explanation why it doesn't work with my files. – cezar Jan 09 '18 at 14:54
  • Weird. Any chance you can share your shapefile? – larsks Jan 09 '18 at 15:00
  • Yes, it is really weird. This is the ZIP file: http://biogeo.ucdavis.edu/data/gadm2.8/shp/ETH_adm_shp.zip. When you unpack it, it is the file(s) `ETH_adm2.shp` (and `shx`, `dbf`, etc.). The first two entries are duplicates, so I needed to remove one. – cezar Jan 09 '18 at 15:31
  • Oddly enough, seems to work fine for me using your shapefile. I guess chalk this one up as a mystery. – larsks Jan 09 '18 at 15:47
  • I tried this today in another virtual machine and it worked. Really weird. – cezar Jan 23 '18 at 10:45
1

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
Marcelo Villa-Piñeros
  • 1,101
  • 2
  • 12
  • 24
  • Thank you for the alternative approach. I had to invest some time in installing GDAL, but after that I could accomplish the task. – cezar Jan 09 '18 at 14:56
  • 1
    I would suggest you use ogr and gdal if you are going to do further analysis either with vector or raster data. If you are interested here is the cookbook with some examples of what you can do with this library: https://pcjericks.github.io/py-gdalogr-cookbook/ – Marcelo Villa-Piñeros Jan 09 '18 at 15:42
  • Can the downvoter please explain the reason for downvoting an accepted answer? – cezar Jan 15 '18 at 16:37