I have files with line segments that cover road network of towns. The issue is that each street with specific name consists of smaller segments that I need to merge into one line covering the whole street.

What I tried in the code below is to read a shapefile, create dictionaries where under a streetId are all of the street's segments and then merge it using ops.linemerge. The problem I have is when saving to the file in the following line


The error shown is

  File "C:\OSGeo4W64\apps\Python37\lib\site-packages\shapefile.py", line 1977, in line
    self._shapeparts(parts=lines, shapeType=shapeType)
  File "C:\OSGeo4W64\apps\Python37\lib\site-packages\shapefile.py", line 2062, in _shapeparts
    for part in parts:
TypeError: 'LineString' object is not iterable

What object should I provide to the writer's line method? Is there any better way to merge the segments into streets?

import shapefile as shp
from shapely import geometry, ops
from shapely.geometry import shape

sf = shp.Reader("shapefiles/town1")
streetShapeDictionary = {}
streetSegmentDictionary = {}
shapes = sf.shapes()
records = sf.records()
fields = sf.fields

recordIndex = 0;
for record in records:
    streetId = record[0]
feature = sf.shapeRecords()[recordIndex].shape.__geo_interface__
linestringShape = shape(feature)
if streetId in streetSegmentDictionary:#add street segment to the list
else:#add new key to the street dictionary
    streetSegmentDictionary[streetId] = [record]
    streetShapeDictionary[streetId] = [linestringShape]
recordIndex = recordIndex + 1

w = shp.Writer('shapefiles/whole_streets')
w.field('name', 'C')
streetShapesArray = []
for street in streetSegmentDictionary:
    for shape in streetShapeDictionary[street]:
    multiline = geometry.MultiLineString([*streetShapesArray])
    merged_line = ops.linemerge(multiline)    
    streetShapesArray = []
  • 1
    merged_line is a Shapely geometry that you cannot use directly with Pyshp. Use w.line(list(merged_line.coords)list(merged_line.coords))
    – gene
    Feb 5, 2021 at 15:20
  • @gene, your suggestion causes the similar error: line 140, in <module> w.line(list(merged_line.coords)) File "C:\OSGeo4W64\apps\Python37\lib\site-packages\shapefile.py", line 1977, in line self._shapeparts(parts=lines, shapeType=shapeType) File "C:\OSGeo4W64\apps\Python37\lib\site-packages\shapefile.py", line 2069, in _shapeparts point = list(point) TypeError: 'float' object is not iterable
    – krltos
    Feb 9, 2021 at 6:57
  • Also, I assume the suggested solution was w.line(list(merged_line.coords)), right?
    – krltos
    Feb 9, 2021 at 7:16
  • 1
    yes, you use only the list of the coordinates of the LineString: line = LineString([(0, 0), (1, 1)]) -> list(line.coords)-> [(0.0, 0.0), (1.0, 1.0)]
    – gene
    Feb 9, 2021 at 8:22


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.