I have one geodataframe that contains polygons and corresponding land use category (e.g. agricultural, commercial, retail, residential, ...) and another that contains census tract polygons and corresponding population. I want to bring the population data from the 2nd dataframe into the first dataframe. Here is the code I'm using:

gdf_chi_pop = gpd.sjoin(gdf_chi, gdf_census, how='inner',op='intersects')

The problem is that gdf_chi_pop has a bunch of extra polygons that don't exist in gdf_chi, which is not what I'm wanting. I just want a new dataframe with populations for all the polygons that already exist in gdf_chi. What I also need to know is how geopandas differentiates between intensive properties (e.g. temperature, sunny days per year, population density, fraction of dogs that are poodles) and extensive properties (e.g. population, number of poodles, number of stores that sell spatulas) in polygons when doing sjoin.

  • 1
    Try intersecting the dataframes then merge/join the columns you want back to the first df
    – BERA
    Aug 23, 2019 at 15:41

2 Answers 2


If you want to retain geometry of gdf_chi, try setting how to 'left'.

gdf_chi_pop = gpd.sjoin(gdf_chi, gdf_census, how='left',op='intersects')

GeoPandas does not differentiate between intensive and extensive properties. It just joins the data from one to the another gdf. No matter the type, it is just copied.


The extra polygons in gdf_chi_pop were actually just duplicates of polygons in gdf_census from where the two sets intersected. It turned out the two key functions I needed were overlay and dissolve, like so:

gdf_chi['landuse_index'] = gdf_chi.index.copy()

Figure out the intersecting geometry:

gdf_chi_pop = gpd.overlay(gdf_census, gdf_chi, how='intersection')

Recalculate extensive quantity population from intensive quantity population density:

gdf_chi_pop['population'] = gdf_chi_pop['pop dnsty'] * gdf_chi_pop['geometry'].area / 5280**2

Recover original geometry from gdf_chi and add populations on regions being joined using aggfunc:

 gdf_chi_fin = gdf_chi_pop.dissolve(by='landuse_index', aggfunc='sum')

Recalculate intensive quantity population density

gdf_chi_fin['pop dnsty'] = gdf_chi_fin['population'] / gdf_chi_fin['geometry'].area * 5280**2

sjoin does not create new geometries. It merely returns the other column values for where the existing geometries intersect.

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.