Search code examples
pythonshapefilegeopandas

Intersection Area of 'n' shapefiles - Python


I have 'n' shapefiles and where they intersect i need to sum a specific attribute. In some points they all intersects, in other points only some of them intersects while in others i don't have any intersection. My final results would be a single shapefile (union of the 'n' shapefiles') where for each intersection area i get the sum of a specific attribute. Is there an easy way to do it, without converting to raster? I already tried with the Geopandas "Overlay" function but without iterating many times i can only get the area where all the shapefiles intersect and not where only some of them intersect.

you can find the shapefiles here: http://www.mediafire.com/folder/2ckfxkfda0asm/shapes

import pandas as pd
import geopandas as gpd
g1 = gpd.GeoDataFrame.from_file("shape1.shp")
g2 = gpd.GeoDataFrame.from_file("shape2.shp")
g3 = gpd.GeoDataFrame.from_file("shape3.shp")
g1['number'] = pd.to_numeric(g1['number'])
g2['number'] = pd.to_numeric(g2['number'])
g3['number'] = pd.to_numeric(g3['number'])
df = pd.concat([g1,g2,g3])
intersection = g1
simmetric = g1
lista = [g2,g3]
for i in lista:
    intersection = gpd.overlay(intersection, i, how='intersection').fillna(0)
    intersection.index = pd.RangeIndex(len(intersection.index))
    intersection.loc[:,'number'] = intersection.loc[:,'number_1'].add(intersection.loc[:,'number_2'])
    intersection.drop(["number_1", "number_2"], axis = 1, inplace = True) 
    simmetric = gpd.overlay(simmetric, i, how='symmetric_difference').fillna(0)
    simmetric.loc[:,'number'] = simmetric.loc[:,'number_1'].add(simmetric.loc[:,'number_2'])
    simmetric.drop(["number_1", "number_2"], axis = 1, inplace = True)     
final_result = pd.concat([simmetric,intersection])
final_result.to_file("result.shp")

example


Solution

  • I think the problem is that you did not properly save intersection and simmertric an output geodataframe. You would have to initialize final_result before the for loop, and concat with itself inside the for loop.

    from shapely.geometry import Polygon
    import geopandas as gpd
    import pandas as pd
    
    polys1 = gpd.GeoSeries([Polygon([(0,0), (2,0), (2,2), (0,2)]),
                                  Polygon([(2,2), (4,2), (4,4), (2,4)])])
    polys2 = gpd.GeoSeries([Polygon([(-1,-1), (1,-1), (1,1), (-1,1)]),
                                  Polygon([(1,1), (3,1), (3,3), (1,3)])])
    polys3 = gpd.GeoSeries([Polygon([(1,1), (3,1), (3,3), (1,3)]),
                                  Polygon([(3,3), (5,3), (5,5), (3,5)]),
                                  Polygon([(6,6), (8,6),(8,8),(6,8)])])
    
    df1 = gpd.GeoDataFrame({'geometry': polys1, 'rate_cars':[10,20]})
    df2 = gpd.GeoDataFrame({'geometry': polys2, 'rate_cars':[100,200]})
    df3 = gpd.GeoDataFrame({'geometry': polys3, 'rate_cars':[1,2,3]})
    
    merge = pd.concat([df1,df2, df3],ignore_index=True)
    
    out = gpd.GeoDataFrame()
    for df in [df1,df2,df3]:
    
        #find which records dont come from the current iteration
        mask = merge.geom_equals(df)
        tmp = merge.copy()
        tmp = tmp[~mask]
    
        #find any non intersection features
        mask1 = tmp.intersects(df)
    
        #non intersectiong features
        non_inter = gpd.overlay(tmp, df, how='symmetric_difference')
        non_inter.loc[:,'total'] = non_inter.sum(axis=1)
        non_inter = non_inter.drop(['rate_cars_1', 'rate_cars_2'], axis=1)
        non_inter = non_inter[['total', 'geometry']]
        non_inter.loc[:,'grid_feature'] = 'street'
        non_inter = non_inter[['total','grid_feature','geometry']]
    
        #find intersections
        res_intersection = gpd.overlay(tmp, df, how='intersection')
        res_intersection.loc[:,'total'] = res_intersection.sum(axis=1)
        res_intersection = res_intersection.drop(['rate_cars_1', 'rate_cars_2'], axis=1)
        res_intersection = res_intersection[['total', 'geometry']]
        res_intersection.loc[:,'grid_feature'] = 'intersection'
        res_intersection = res_intersection[['total','grid_feature','geometry']]   
    
        out = pd.concat([out, res_intersection, non_inter])
    
    out = out.drop_duplicates()  
    
    
    

    Where out returns:

       total  grid_feature                                           geometry
    0  110.0  intersection  POLYGON ((0.00000 1.00000, 1.00000 1.00000, 1....
    1  210.0  intersection  POLYGON ((1.00000 1.00000, 1.00000 2.00000, 2....
    2   11.0  intersection  POLYGON ((1.00000 1.00000, 1.00000 2.00000, 2....
    3  220.0  intersection  POLYGON ((2.00000 3.00000, 3.00000 3.00000, 3....
    4   21.0  intersection  POLYGON ((2.00000 3.00000, 3.00000 3.00000, 3....
    5   22.0  intersection  POLYGON ((3.00000 3.00000, 3.00000 4.00000, 4....
    0  100.0        street  POLYGON ((-1.00000 -1.00000, -1.00000 1.00000,...
    1  200.0        street  MULTIPOLYGON (((1.00000 2.00000, 1.00000 3.000...
    2    1.0        street  MULTIPOLYGON (((1.00000 2.00000, 1.00000 3.000...
    3    2.0        street  POLYGON ((3.00000 4.00000, 3.00000 5.00000, 5....
    4    3.0        street  POLYGON ((6.00000 6.00000, 6.00000 8.00000, 8....
    5   10.0        street  MULTIPOLYGON (((0.00000 1.00000, 0.00000 2.000...
    6   20.0        street  MULTIPOLYGON (((2.00000 3.00000, 2.00000 4.000...
    0  110.0  intersection  POLYGON ((0.00000 0.00000, 0.00000 1.00000, 1....
    1  200.0  intersection  POLYGON ((-1.00000 -1.00000, -1.00000 1.00000,...
    2  210.0  intersection  POLYGON ((1.00000 2.00000, 2.00000 2.00000, 2....
    3  220.0  intersection  POLYGON ((2.00000 2.00000, 2.00000 3.00000, 3....
    4  400.0  intersection  POLYGON ((1.00000 1.00000, 1.00000 3.00000, 3....
    5  201.0  intersection  POLYGON ((1.00000 1.00000, 1.00000 3.00000, 3....
    1   20.0        street  POLYGON ((2.00000 3.00000, 2.00000 4.00000, 4....
    2    2.0        street  POLYGON ((3.00000 3.00000, 3.00000 5.00000, 5....
    0   11.0  intersection  POLYGON ((1.00000 2.00000, 2.00000 2.00000, 2....
    1   21.0  intersection  POLYGON ((2.00000 2.00000, 2.00000 3.00000, 3....
    3    2.0  intersection  POLYGON ((1.00000 1.00000, 1.00000 3.00000, 3....
    4   22.0  intersection  POLYGON ((3.00000 4.00000, 4.00000 4.00000, 4....
    5    4.0  intersection  POLYGON ((3.00000 3.00000, 3.00000 5.00000, 5....
    6    6.0  intersection  POLYGON ((6.00000 6.00000, 6.00000 8.00000, 8....
    0   10.0        street  POLYGON ((0.00000 0.00000, 0.00000 2.00000, 1....
    2  100.0        street  POLYGON ((-1.00000 -1.00000, -1.00000 1.00000,...