Python – Fixing ‘TypeError: Polygon Object is Not Iterable’ in Python

geopandasintersectionoverlapping-featurespolygonpython

I refer to this example notebook resource that shows how to identify intersection regions between polygons:
https://nbviewer.org/gist/jorisvandenbossche/3a55a16fda9b3c37e0fb48b1d4019e65

Here in this example, with credit going to the author of that example notebook above, we start with 3 circles that happen to all overlap:

enter image description here

We then try to find all of the new intersected polygons made up by these overlapping polygons via this code:

all_intersections = [a.intersection(b) for a, b in list(itertools.combinations(s, 2))]
s_all = pd.concat([s, geopandas.GeoSeries(all_intersections)])
polys = list(shapely.ops.polygonize(s_all.boundary.unary_union))
polys = geopandas.GeoSeries(polys)
polys.plot(cmap='Set1')

to get this plot of our three overlapping circles with each new intersected polygon identified, and so we now have 7 polygons identified, just what I want:

enter image description here

And then just running polys I see the geometries for each of these 7 newly intersected polygons printed, great:

enter image description here

Though what I am trying to figure out how to do is how to loop through each unique polygon in the initial GeoDataFrame and identify only the polygon intersections within that specific polygon.

So going with this new example:

enter image description here

For circle A would just get the geometry for circle A itself returned, and then for circle B, I would just get the intersections within circle B returned:

enter image description here

And for circle E, I would get just the intersections within circle E returned:

enter image description here

And so on, repeating this process for each unique circle.

How can I augment my above polygon intersection code to accommodate a for loop to iterate through each unique circle and only identify the intersected polygons within that specific polygon?

I have tried this:

for index, row in polygons.iterrows():
    
    all_intersections = [a.intersection(b) for a, b in list(itertools.combinations(row['geometry'], 2))]
    polygons_all = pd.concat([polygons, gpd.GeoSeries(all_intersections)])
    polys = list(shapely.ops.polygonize(polygons_all.boundary.unary_union))
    polys = gpd.GeoSeries(polys)

but am just getting errors, specifically:

TypeError: 'Polygon' object is not iterable

Best Answer

I am no expert on GeoPandas, not having used it all that much, so my adaptation of the code in your question may not be the cleanest or most efficient but, testing on a made-up data set, this seems to do what you are after:

import geopandas as gpd
import pandas as pd
import itertools
import shapely

# Path to your polygons file
shp_path = '/home/path/to/polygons.shp'
gdf = gpd.read_file(shp_path)
gdf.boundary.plot()

def get_intersections(i):
    # Current polygon
    current = gdf.iloc[i]
    # All other polygons with current dropped
    others = gdf.drop(i)
    # Get all other intersections with current
    ix = [current.geometry.intersection(other) for other in others.geometry if current.geometry.intersects(other)]
    if ix:
        s = pd.concat([gpd.GeoSeries(current.geometry), gpd.GeoSeries(ix)])
        # Get all combinations of intersections
        all_ix = [a.intersection(b) for a, b in list(itertools.combinations(s, 2))]
        return pd.concat([gpd.GeoSeries(current.geometry), gpd.GeoSeries(all_ix)])
    else:
        return gpd.GeoSeries(current.geometry)


for i in range(gdf.shape[0]):
    s = get_intersections(i)
    polys = list(shapely.ops.polygonize(s.boundary.unary_union))
    polys = gpd.GeoSeries(polys)
    polys.plot(cmap='Set2')

Resulting plots:

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here