I have 3 dataframes: df1 (large polygons); df2 (small polygons, which overlays with large polygons) and df3 (points).

How do I exclude large polygons in which points do not overlay with the small polygons?

Below is an example of two polygons (purple) that overlays with the small polygons, together with some points in and outside them.

Polygon No. 1: points overlay with each small polygon within a large one, meaning this large polygon is not excluded.

Polygon No.2: none of the points overlay with a small polygon within a large one, meaning that this large polygon should be excluded.

In short, I need to identify large polygons in which points DO NOT overlay with small polygons and remove them. The result would be df1 with the removed polygons.

enter image description here

So, there is a solution with GeoPandas SpatialJoin using two dataframes. In this case, if small polygons do not overlay with large polygons, the particular polygon from df1 is excluded. But how can this be done using another data frame?

import geopandas as gpd
df1 = gpd.read_file(r'/home/../large_poly.shp')
df2 = gpd.read_file(r'/home/../small_poly.shp')

df3 = gpd.read_file(r'/home/../points.shp')

df1['savedindex']= df1.index #Save the index values as a new column

intersecting = df2.sjoin(df1, how='inner')['savedindex'] 

df1 = df1[df1.savedindex.isin(intersecting)] 

2 Answers 2


You can clip the points using the smaller polygons, then subset the larger polygons using a lambda function to find which ones contain any remaining points, such as:

import geopandas as gpd

#read in data
large = gpd.read_file(r'./polys.shp')
small = gpd.read_file(r'./polys2.shp')
points = gpd.read_file(r'./points.shp')

#clip points using small polys
points_subset = gpd.clip(points,small)

#filter polys based on remaining points
polys_subset =large[large.geometry.apply(lambda x: points_subset.within(x).any())]

#write output 

Input data:

enter image description here

With output in pink:

enter image description here


Use three spatial joins:

import geopandas as gpd

large = gpd.read_file(r'/home/bera/GIS/Data/testdata/largepoly.shp')
large['largeid'] = large.index

small = gpd.read_file(r'/home/bera/GIS/Data/testdata/smallpoly.shp')
point = gpd.read_file(r'/home/bera/GIS/Data/testdata/points.shp')

pointswithinlarge = gpd.sjoin(left_df=point, right_df=large, how='inner')[['geometry']] #Keep only geometry
smallwithpointwithinlarge = gpd.sjoin(left_df=small, right_df=pointswithinlarge, how='inner')[['geometry']]
largetodrop = gpd.sjoin(left_df=large, right_df=smallwithpointwithinlarge, how='inner')['largeid'] #Keep id

large = large[~large.largeid.isin(largetodrop)] #~ means "is not in"

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.