0

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]})
3
  • See Converting huge multipolygon to polygons
    – gene
    Mar 11, 2019 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, 2019 at 9:43
  • It's because there are polygons and multipolygons in the shapefile
    – gene
    Mar 18, 2019 at 17:53

1 Answer 1

0

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',
                    driver=source.driver,
                    crs=source.crs,
                    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
                output.write({
                    '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
                    output.write({
                        'properties': multi['properties'],
                        'geometry': mapping(poly)
                    })
            else:
                raise ValueError('Unhandled geometry type: {}'.format(polygon_shape))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.