'Combine and sum values of overlapping Polygons in GeoPandas

I have a GeoPandas dataframe with a.o. polygons as 'geometry' column and a corresponding value in a different column. E.g. like such:

import numpy as np
import geopandas as gpd
xmin, xmax, ymin, ymax = 900000, 1080000, 120000, 280000
xc = (xmax - xmin) * np.random.random(2000) + xmin
yc = (ymax - ymin) * np.random.random(2000) + ymin
gdf = gpd.GeoDataFrame(geometry=gpd.points_from_xy(xc,yc),crs=3857)
gdf['geometry'] = gdf['geometry'].buffer(5000)
gdf['value'] = np.random.random(2000)

gdf.head()
                                             geometry    value
0  POLYGON ((1058397.021 237842.681, 1058372.944 ...  0.792110
1  POLYGON ((907562.671 276549.404, 907538.595 27...  0.124436
2  POLYGON ((953685.557 229083.936, 953661.481 22...  0.264356
3  POLYGON ((1052030.845 242915.680, 1052006.769 ...  0.161183
4  POLYGON ((1063942.060 263330.293, 1063917.983 ...  0.972290

What I would like to do is create new polygons describing the overlap of all polygons and sum the values of these overlapping polygons, as in the picture below:

Example

I've looked at dissolve and at unary_union, but these do not seem to do the trick. Any suggestions are appreciated.



Solution 1:[1]

For anyone intersted in a solution for this, here is an example that solves a similar problem.

First create the geodataframe:

from shapely.geometry import Polygon
import geopandas
from shapely.ops import linemerge, unary_union, polygonize

dftest = geopandas.GeoDataFrame({'geometry': geopandas.GeoSeries([Polygon([(0,0), (3,0), (3,3), (0,3)]),
                                                                              Polygon([(0,0), (2,0), (2,2), (0,2)]),
                                                                            Polygon([(2,2), (4,2), (4,4), (2,4)]),
                                                                            Polygon([(1,1), (3,1), (3,3), (1,3)]),
                                                                            Polygon([(3,3), (5,3), (5,5), (3,5)])])}
                                            ).reset_index()
       
dftest['values'] = [4,3,2,1,0]

Plot this:

dftest.plot('values', legend=True)

initial geodataframe

convert all polygons to lines and perform union:

lines = unary_union(linemerge([geom.exterior for geom 
                           in dftest.geometry]))

Convert again to (smaller) intersecting polygons and to geodataframe:

polygons = list(polygonize(lines))
intersects = geopandas.GeoDataFrame({'geometry': polygons})

Perform sjoin with original geoframe to get overlapping polygons. Afterwards group per intersecting polygon to perform (arbitrary) aggregation.

intersects['sum_overlaps'] = (intersects
                        .sjoin(dftest, predicate='within')
                        .reset_index()
                        .groupby(['level_0', 'index_right'])
                        .head(1)
                        .groupby('level_0')
                        .values.sum())

plot result

intersects.plot('sum_overlaps', legend=True)

overlap result

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1