Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

I have a piece of software (not Arc) that runs nightly on a non-production machine which updates shapefile features from an external database. Periodically I would like to delete all of the features in the shapefile (not the file itself, which must remain) and let the software "rebuild" the shapefile from scratch. I would like to automate this process.

I don't have any GIS software currently installed on that machine. I was hoping that I could script a routine in Python that would automatically delete the features, much like Arc's Delete Features geoprocessing tool.

Are there any Python modules that would allow me to do this? Preferrably open-source? I looked at Shapely and PyShp but didn't see anything that would allow me to delete the features in mass or that matched a WHERE clause. They can write features and analyze them, but haven't seen DELETE FEATURES functions anywhere.

I must certainly be missing something simple...

share|improve this question
add comment

4 Answers

up vote 15 down vote accepted

You can use the GDAL/OGR python API, the code will be like that:

from osgeo import ogr

shapefile = ogr.Open( "shapfile.shp",1 )
layer=shapefile.GetLayerByIndex(0)
count=layer.GetFeatureCount()
for feature in range(count):
    layer.DeleteFeature(feature)
share|improve this answer
    
I get ERROR 1: The DeleteFeature() operation is not permitted on a read-only shapefile –  matt wilkie Nov 3 '11 at 23:07
2  
you have to open it for writing. Do it with: ogr.Open('shapefile.shp', 1) –  capooti Nov 3 '11 at 23:25
add comment

The command line ogr2ogr with a where clause guaranteed to create empty results is one quick and easy method:

ogr2ogr output.shp input.shp -where "FID < 0"

The overview page for python and OGR (and GDAL) is http://trac.osgeo.org/gdal/wiki/GdalOgrInPython

share|improve this answer
    
I like the idea. I would have to do some scripting around deleting the input file and renaming the output file back to the input name, but I could make it work if no other solutions are presented. –  RyanDalton Nov 3 '11 at 22:40
1  
here's a one line batch file for that: for %%a in (sample.shp) do (ogr2ogr %temp%\xxx.shp %%a -where "FID < 0" && copy %temp%\xxx.* %%~na.*). Pablo's answer is more extensible though. –  matt wilkie Nov 3 '11 at 23:05
add comment

Why not save a copy of the blank Shapefile and over-write your Shapefile of interest.

share|improve this answer
    
Ironically, IMHO this would be the most efficient solution as long as the schema does not change much... –  Ragi Yaser Burhum Nov 4 '11 at 0:48
    
If it was for 1 or 2 files, I would agree. The main reason this wouldn't be as effecient is because I have 35 folders (different geographic extents, all in their own projection), with 35-65 shapefiles. The math says that would be 1000+ blank shapefiles to manage, which isn't practical either. Scripting a process to discover shapefiles & delete features is what I ultimately hope to end up with. –  RyanDalton Nov 4 '11 at 14:26
    
@RyanDalton in the Q you said "the shapefile", which led us, well me anyway, to think of and devise a singular solution. I'm not complaining, just pointing out that more information about the use case up front might have led to answers more immediately applicable more quickly. –  matt wilkie Nov 6 '11 at 4:24
add comment

You can do this in pyshp. It's simple but not obvious because I never envisioned this use case. But it does make sense for automated update applications. I tested the following 6 lines of code and it worked great:

import shapefile
r = shapefile.Reader("myshape")
w = shapefile.Writer(r.shapeType)
# This line will give us the same dbf schema
w.fields = r.fields
# Use the original bounding box as a place holder in the header
w.bbox = lambda: r.bbox
w.save("myshape")

You now have a shapefile written over the original that has correct headers and the original dbf fields. It will open safely in GIS software and shapefile libraries but has no features or dbf records.

The lambda function transfers the original bounding box over as a placeholder. You can put what ever float values you want in an array of [xmin, ymin, xmax, ymax]. Example:

w.bbox = lambda: [0.0, 0.0, 0.0, 0.0]

Changing dbf fields is simple too and documented in the pyshp docs.

Hope that helps.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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