I used the code from Dissolving polygons based on multiple attributes with Python (shapely and fiona)? to dissolve a shapefile using shapely and fiona. However the output creates multi-part geometries.

Is it possible to convert the output to single part or generate single part features instead?

I'm attempting to create a single chain using open source tools in Linux. I would also like to avoid calling QGIS tools if that's at all possible.

Here's the code sample:

from shapely.geometry import shape, mapping
from shapely.ops import unary_union
import fiona
import itertools
with fiona.open('cb_2013_us_county_20m.shp') as input:
    # preserve the schema of the original shapefile, including the crs
    meta = input.meta
    with fiona.open('dissolve.shp', 'w', **meta) as output:
        # groupby clusters consecutive elements of an iterable which have the same key so you must first sort the features by the 'STATEFP' field
        e = sorted(input, key=lambda k: k['properties']['STATEFP'])
        # group by the 'STATEFP' field 
        for key, group in itertools.groupby(e, key=lambda x:x['properties']['STATEFP']):
            properties, geom = zip(*[(feature['properties'],shape(feature['geometry'])) for feature in group])
            # write the feature, computing the unary_union of the elements in the group with the properties of the first element in the group
            output.write({'geometry': mapping(unary_union(geom)), 'properties': properties[0]})
  • See Converting huge multipolygon to polygons – gene Mar 11 '19 at 16:33
  • Hi, thanks for that. Sorry it's taken a while to get back to you. I've tried the code but I get an error on the line: # extract each Polygon feature' for poly in shape(multi['geometry']): TypeError: 'Polygon' object is not iterable – MattEnvSys Mar 18 '19 at 9:43
  • It's because there are polygons and multipolygons in the shapefile – gene Mar 18 '19 at 17:53

I had an error due to the input shapefiles being a mixture of polygon and multipolygon types. I've included some code to skip the for loop for polygon types.

import fiona
from shapely import geometry
from shapely.geometry import shape, mapping

# open the original MultiPolygon file
with fiona.open('/home/matt/share/zoning/dissolve2.shp') as source:
    # create the new file: the driver and crs are the same
    # for the schema the geometry type is "Polygon" instead
    output_schema = dict(source.schema)  # make an independant copy
    output_schema['geometry'] = "Polygon"

    with fiona.open('/home/matt/share/zoning/output.shp', 'w',
                    schema=output_schema) as output:

        # read the input file
        for multi in source:

            polygon_shape = shape(multi['geometry'])

            if isinstance(polygon_shape, geometry.Polygon):

                # write the Polygon feature
                    'properties': multi['properties'],
                    'geometry': mapping(polygon_shape)
            elif isinstance(polygon_shape, geometry.MultiPolygon):
                # extract each Polygon feature
                for poly in polygon_shape:

                    # write the Polygon feature
                        'properties': multi['properties'],
                        'geometry': mapping(poly)
                raise ValueError('Unhandled geometry type: {}'.format(polygon_shape))

Your Answer

