# Creating Shapely MultiPolygons from shapefile MultiPolygons

I'm reading a shapefile using Fiona:

``````with fiona.open('data/boroughs/boroughs_n.shp') as source:
mpolys = [p for p in source]
candidate = polys[0]['geometry']
``````

this gives me a dict containing a list of lists of coordinates, and type 'MultiPolygon' However, I'm not sure how to use the coordinates data to create a Shapely MultiPolygon, since it requires `a sequence of exterior ring and hole list tuples: [((a1, ..., aM), [(b1, ..., bN), ...]), ...].`

Is there a 'correct' way of doing this, using Fiona and Shapely?

You can use the shape function of Shapely:

``````from shapely.geometry import shape
c = fiona.open('data/boroughs/boroughs_n.shp')
pol = c.next()
geom = shape(pol['geometry'])
``````

and a MultiPolygon is a list of Polygons,so

``````Multi = MultiPolygon([shape(pol['geometry']) for pol in fiona.open('data/boroughs/boroughs_n.shp')])
``````

Example with one of my data:

``````# the dictionaries
for pol in fiona.open('poly.shp'):
print pol['geometry']

{'type': 'Polygon', 'coordinates': [[(249744.23153029341, 142798.16434689672),   (250113.79108725351, 142132.95714436853), (250062.62130244367, 141973.76225829343), (249607.77877080048, 141757.71205576291), (249367.77424759799, 142304.68402918623), (249367.77424759799, 142304.68402918623), (249744.23153029341, 142798.16434689672)]]}
{'type': 'Polygon', 'coordinates': [[(249175.78991730965, 142292.53526406409), (249367.77424759799, 142304.68402918623), (249607.77877080048, 141757.71205576291), (249014.45396077307, 141876.13484290778), (249175.78991730965, 142292.53526406409)]]}
{'type': 'Polygon', 'coordinates': [[(249026.74622412826, 142549.13626160321), (249223.42243781092, 142496.89414234375), (249175.78991730965, 142292.53526406409), (249026.74622412826, 142549.13626160321)]]}
...
``````

and

`````` # MultiPolygon from the list of Polygons
Multi = MultiPolygon([shape(pol['geometry']) for pol in fiona.open('poly.shp')])
Multi.wkt
'MULTIPOLYGON (((249744.2315302934148349 142798.1643468967231456, 250113.7910872535139788 142132.9571443685272243, 250062.6213024436729029 141973.7622582934272941, 249607.7787708004761953 141757.7120557629095856, 249367.7742475979903247 142304.6840291862317827, 249367.7742475979903247 142304.6840291862317827, 249744.2315302934148349 142798.1643468967231456)), ((249175.7899173096520826 142292.5352640640921891, 249367.7742475979903247 142304.6840291862317827, 249607.7787708004761953 141757.7120557629095856, 249014.4539607730694115 141876.1348429077770561, 249175.7899173096520826 142292.5352640640921891)), ((249026.7462241282628383 142549.1362616032129154, 249223.4224378109211102 142496.8941423437499907, 249175.7899173096520826 142292.5352640640921891, 249026.7462241282628383 142549.1362616032129154)), ((249244.9338986824732274 142733.5202119307068642, 249744.2315302934148349 142798.1643468967231456, 249367.7742475979903247 142304.6840291862317827, 249367.7742475979903247 142304.6840291862317827, 249367.7742475979903247 142304.6840291862317827, 249175.7899173096520826 142292.5352640640921891, 249223.4224378109211102 142496.8941423437499907, 249244.9338986824732274 142733.5202119307068642)), ((249870.8182051893090829 142570.3083320840960369, 250034.3015973484434653 142613.6706442178401630, 250152.6146321419219021 142438.5058914067049045, 250015.3392731740023009 142310.1704097116598859, 249870.8182051893090829 142570.3083320840960369)))'
``````
• That worked perfectly, I just had to insert some handling when plotting using Descartes because some shapes in the file were Polygon, not MultiPolygon. Thanks! Commented Sep 4, 2013 at 20:40
• Couldn't have said it better myself, gene! Commented Sep 4, 2013 at 22:37

If speed is an issue, it is faster to create the multipolygon from the raw coordinates.

This is about 5x faster than the previously suggested solution of first having to create several polygon objects and then creating the multipolygon object from those.

Here is how to do it:

``````# first retrieve the coordinates from your geojson dictionary
rawcoords = candidate["coordinates"]

# define the conversion function
def PrepCoordsForShapely(rawcoords):
preppedcoords = []
#according to the geojson specs, a multipolygon is a list of linear rings, so we loop each
for eachpolygon in rawcoords:
#the first linear ring is the coordinates of the polygon, and shapely needs it to be a tuple
tupleofcoords = tuple(eachpolygon[0])
#the remaining linear rings, if any, are the coordinates of inner holes, and shapely needs these to be nested in a list
if len(eachpolygon) > 1:
listofholes = list(eachpolygon[1:])
else:
listofholes = []
#shapely defines each polygon in a multipolygon with the polygoon coordinates and the list of holes nested inside a tuple
eachpreppedpolygon = (tupleofcoords, listofholes)
#so append each prepped polygon to the final multipolygon list
preppedcoords.append(eachpreppedpolygon)
#finally, the prepped coordinates need to be nested inside a list in order to be used as a star-argument for the MultiPolygon constructor.
return [preppedcoords]

# use the function to prepare coordinates for MultiPolygon
preppedcoords = PrepCoordsForShapely(rawcoords)
# use the prepped coordinates as a star-argument for the MultiPolygon constructor
shapelymultipolygon = MultiPolygon(*preppedcoords)
``````