2

I have a shapefile (blockgroups.shp) that I downloaded from: https://github.com/GeospatialPython/pyshp/tree/master/shapefiles

I want to create a new Shapefile with only four attributes (bkg_key, pop1990, white and black) using PyShp.

I've tried with this code:

import shapefile
file= "blockgroups.shp"
outFile = "newblockgroup3000"
sf = shapefile.Reader(file)
shapeRec= sf.shapeRecords()
w = shapefile.Writer(shapefile.POLYGON)
w.field('BKG_KEY', 'C', 40)
w.field('POP1990', 'N', 40)
w.field('NWHITES', 'N', 40)
w.field('NBLACKS', 'N', 40)
for row in shapeRec:
    bkg_key = row.record[1]
    pop1990 = row.record[2]
    white = row.record[7]
    black = row.record[8]
    points = row.shape.points
    parts = row.shape.parts
    w.parts = parts
    w.poly([points])
    w.record(bkg_key,pop1990,white,black)
    w.save(outFile)

It works for all the shapes except for one.

There is a record that has more than one part. The record which has more than one part is 'BKG_KEY = 060750601001' and 'POP = 4531'. In the new shapefile, this record has a strange shape because pyShp automatically connects the first and the last vertexs which come from different parts of the feature.

If I only select the records that 'POP1990 <4531' and the records that 'POP1990>4531'(excluding the mentioned record) it works so the problem only happens when there are records with multiple parts.

Is there any way to keep the number of parts of the original shapefile when I create the new one? How can I handle this problem.

I would appreciate some help. Thanks

Daniel
  • 87
  • 1
  • 7

1 Answers1

0

I found this question whilst looking for a solution to save multiple shapes in one shapefile using pyshp. Your code helped me solve my problem and so i'll provide a solution for this.

import shapefile

file= "blockgroups.shp"
outFile = "newblockgroup3000"
sf = shapefile.Reader(file)
shapeRec= sf.shapeRecords()
w = shapefile.Writer(shapefile.POLYGON)
w.field('BKG_KEY', 'C', 40)
w.field('POP1990', 'N', 40)
w.field('NWHITES', 'N', 40)
w.field('NBLACKS', 'N', 40)

for row in shapeRec:
    bkg_key = row.record[1]
    pop1990 = row.record[2]
    white = row.record[7]
    black = row.record[8]
    points = row.shape.points
    parts = row.shape.parts
    geom = []

    # handle parts here
    for i in range(len(parts)):
        xy = []
        pt = None
        if i < len(parts) - 1:
            pt = points[parts[i]:parts[i + 1]]
        else:
            pt = points[parts[i]:]
        for x, y in pt:
            xy.append([x, y])
        geom.append(xy)

    w.poly(geom)
    w.record(bkg_key,pop1990,white,black)
w.save()

Result before edit: enter image description here

Result after edit: enter image description here

TennyApps
  • 189
  • 8
  • Thank you, I appreciate. I even found an easier solution that worked in previous versions of pyshp (versions 1.x) but it doesn't in the newest ones (versions 2.x). The library has significantly changed so I had to update the script I once wrote and your solution has been very helpful. However, be careful because your script might not work if you install the latest pyshp version. – Daniel May 27 '19 at 14:27
  • Now, the Writer() argument has to be the name of the new file (not the geometry type) and you don't need to save the shapefile at the end of the script using save(). I recommend you to have a look at the documentation of the pyshp's newest version. You'll probably need to update your scripts because of those changes. – Daniel May 27 '19 at 14:28