Search code examples
pythonjupyter-notebookdata-visualizationcartopy

'Polygon' object is not iterable- iPython Cookbook


I am learning visualization of data in python using Cartopy

I have this code for plotting Africa's population and GDP.

def choropleth(ax, attr, cmap_name):
    # We need to normalize the values before we can
    # use the colormap.
    values = [c.attributes[attr] for c in africa]
    norm = Normalize(
        vmin=min(values), vmax=max(values))
    cmap = plt.cm.get_cmap(cmap_name)
    for c in africa:
        v = c.attributes[attr]
        sp = ShapelyFeature(c.geometry, crs,
                            edgecolor='k',
                            facecolor=cmap(norm(v)))
        ax.add_feature(sp)


fig, (ax1, ax2) = plt.subplots(
    1, 2, figsize=(10, 16),
    subplot_kw=dict(projection=crs))
draw_africa(ax1)
choropleth(ax1, 'POP_EST', 'Reds')
ax1.set_title('Population')

draw_africa(ax2)
choropleth(ax2, 'GDP_MD_EST', 'Blues')
ax2.set_title('GDP')

And the expected output should be- enter image description here

But I am getting an error as such -

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-41-b443c58ecbd5> in <module>
      3     subplot_kw=dict(projection=crs))
      4 draw_africa(ax1)
----> 5 choropleth(ax1, 'POP_EST', 'Reds')
      6 ax1.set_title('Population')
      7 

<ipython-input-40-161126226479> in choropleth(ax, attr, cmap_name)
      8     for c in africa:
      9         v = c.attributes[attr]
---> 10         sp = ShapelyFeature(c.geometry, crs,
     11                             edgecolor='k',
     12                             facecolor=cmap(norm(v)))

~/anaconda3/lib/python3.8/site-packages/cartopy/feature/__init__.py in __init__(self, geometries, crs, **kwargs)
    219         """
    220         super(ShapelyFeature, self).__init__(crs, **kwargs)
--> 221         self._geoms = tuple(geometries)
    222 
    223     def geometries(self):

TypeError: 'Polygon' object is not iterable

I tried searching for this issue on github but no to avail. Can anyone please help me out how can I correct this ?

Here is the site for reference .


Solution

  • The issue is that the code tries to pass a shapely Polygon to a function that expects MultiPolygon. The elegant solution by swatchai here https://stackoverflow.com/a/63812490/13208790 is to catch Polygons and put them in a list so they can be treated as MultiPolygons.

    Here's the code adapted to your case:

    for i, c in enumerate(africa):
        v = c.attributes[attr]
        print(i)
        # swatchai's Polygon catch logic
        if c.geometry.geom_type=='MultiPolygon':
            # this is a list of geometries
            sp = ShapelyFeature(c.geometry, crs,
                            edgecolor='k',
                            facecolor=cmap(norm(v)))
        elif c.geometry.geom_type=='Polygon': 
            # this is a single geometry
            sp = ShapelyFeature([c.geometry], crs,
                                    edgecolor='k',
                                    facecolor=cmap(norm(v)))   
        else:
            pass  #do not plot the geometry