Search code examples
pythonshapefilepyshp

Creating a shapefile of straight segments with pyshp?


Using Python and the pyshp library, I am attempting to create a shapefile from the data below (stored in a list):

edge_list = [
    [-40.5, -20.666],
    [-39.849998, -18.700001],
    [-39.816002, -19.6],
    [-40.071999, -19.391001],
    [-40.150002, -19.933001],
    [-39.733002, -18.533001],
    [-39.833, -18.733],
    [-39.708, -18.419001],
    [-39.370998, -17.891001],
    [-39.200001, -17.417],
    [-39.216999, -17.299999],
    [-39.167, -17.083],
    [-39.049999, -16.433001],
    [-38.932999, -13.967],
    [-39.083, -16.583],
    [-39.0, -13.916],
    [-38.900002, -13.6],
]

Here is a segment of my code (where edge_list is the list above):

w = shapefile.Writer()
w.line(parts=[edge_list])
w.field("COMMON_ID", 'C')
w.save("test")

I get this:

enter image description here

But I want to get this:

enter image description here

Any hints?

EDIT: Here is the complete test code, but there is not much to it. The file "temp.csv" just contains the two columns of points shown above, separated by commas and with an extra line for headers (x, y).

import csv
import shapefile

data = csv.reader(open("test.csv", "rb"), delimiter = ',')
data.next() # skip header line
edge_list = []
for row in data:
    edge_list.append([float(row[0]), float(row[1])])

for e in range(len(edge_list)):
    print "x=", edge_list[e][0], "y=", edge_list[e][1]

w = shapefile.Writer()
w.line(parts=[edge_list])
w.field("COMMON_ID", 'C')
w.save("test")

Solution

  • Disclaimer: I've not used shapefiles or pyshp. But I know my way around drawing lines.

    What I'm seeing is that it's drawing the lines in the order that you entered the points. It's connecting the dots, and that's the order your dots are given. What you need to do is re-order the points in edge_list.

    In your case, your dots will look good if your y-variable is ordered.

    So, try replacing this line:

    w.line(parts=[edge_list])
    

    with this:

    w.line(parts=sorted(edge_list, key=lambda point: point[1]))
    

    This will sort your points by the y-variable, and should draw the line the way you want.