GeospatialPython / pyshp

This library reads and writes ESRI Shapefiles in pure Python.
MIT License
1.1k stars 259 forks source link

How to merge several shapefile? #191

Closed maleco50 closed 3 years ago

maleco50 commented 5 years ago

I'm trying to merge a large number of shapfile with this piece of code:

sf = shapefile.Writer(output_shapefile)

for shape in file_list: current_path = os.path.join(input_dir, shape) if current_path.endswith(".shp"): logger.info("current_path %s",current_path) r = shapefile.Reader(current_path) sf._shapes.extend(r.shapes()) sf.records.extend(r.records())

However, I have the following error: AttributeError: 'Writer' object has no attribute '_shapes'

And I can't find any documentation or examples to meet my needs. Can you give me the new features that allow me to merge?

BrianBunker commented 4 years ago

Your code mimicks the answer in this S.O. post, but it no longer works on current versions of pyshp.

You can see an example of copying from one shapefile to another on the repo readme under the subheading Adding from an existing Shape object.

I'm currently working on the same issue and have this so far. Unfortunately it requires iterating through every feature of the shapefile, instead of just extending a list of shapes/records.

import shapefile as pyshp

def merge_shapefiles(shapefiles, out_shapefile):
   '''Merge shapefiles into one'''

   with pyshp.Writer(out_shapefile) as shp_writer:
       for shapefile in shapefiles:
           with pyshp.Reader(shapefile) as shp_reader:
               if not shp_writer.fields:
                   shp_writer.fields = shp_reader.fields[1:]
               for shp_record in shp_reader.iterShapeRecords():
                   shp_writer.record(*shp_record.record)
                   shp_writer.shape(shp_record.shape)
maleco50 commented 4 years ago

Thank you for the answer, but it doesn't work for me. I have this error message:

with shapefile.Reader(current_path) as shp_reader: File "/home/maleco/.local/lib/python2.7/site-packages/shapefile.py", line 553, in init self.load(args[0]) File "/home/maleco/.local/lib/python2.7/site-packages/shapefile.py", line 648, in load self.shpHeader() File "/home/maleco/.local/lib/python2.7/site-packages/shapefile.py", line 730, in shpHeader self.shpLength = unpack(">i", shp.read(4))[0] * 2 struct.error: unpack requires a string argument of length 4

I think it's the reader doesn't work, however I have not yet found the solution

karimbahgat commented 3 years ago

Not sure what that last error is, if you still have the same problem, just open a new issue and give some more details about your PyShp version and the shapefile contents.

As for the merge example, @BrianBunker's code should work, but note that this assumes all files have the exact same fields (field names+field types). If some of the shapefiles are slightly different you would need a more complicated function to possibly merge different fields from different shapefiles and ensure the values are the correct type across shapefiles.

Going forward I do think it would be useful to extend the documentation with common recipes such as this one, PRs more than welcome :)

prasanjitdash commented 2 years ago

Your code mimicks the answer in this S.O. post, but it no longer works on current versions of pyshp.

You can see an example of copying from one shapefile to another on the repo readme under the subheading Adding from an existing Shape object.

I'm currently working on the same issue and have this so far. Unfortunately it requires iterating through every feature of the shapefile, instead of just extending a list of shapes/records.

import shapefile as pyshp

def merge_shapefiles(shapefiles, out_shapefile):
   '''Merge shapefiles into one'''

   with pyshp.Writer(out_shapefile) as shp_writer:
       for shapefile in shapefiles:
           with pyshp.Reader(shapefile) as shp_reader:
               if not shp_writer.fields:
                   shp_writer.fields = shp_reader.fields[1:]
               for shp_record in shp_reader.iterShapeRecords():
                   shp_writer.record(*shp_record.record)
                   shp_writer.shape(shp_record.shape)

Works pretty well, thanks. Is it possible to create the projection information .prj file?