I have a geoseries where each row is a (square) polygon. Housing price data is in a geodataframe where the geometry is a polygon of the zip code.

I need to aggregate the housing price data by squares in the geoseries.

For example for a square that is within a zip code the value would be the housing price of the zip code. When the square in the geoseries intersects many zip codes I would like to get the weighted average of the housing prices in the zip codes, where the weights would be the shares of the areas intersected by each zip code. (Or if this weighted average is difficult, I could take the price from the zip code whose share is greatest in the square)


2 Answers 2


Intersect the dataframes then groupby and calculate weighted mean using intersection areas as weights.


import geopandas as gpd
import pandas as pd
import numpy as np

zip_areas = gpd.read_file('/home/bera/GIS/data/test/kommun.shp')
prices = gpd.read_file('/home/bera/GIS/data/test/housing_prices.shp')

price_column = 'price'
zip_area_id_column = 'county_id'

inter = gpd.overlay(zip_areas,prices)
inter['area'] = inter.area

wm = lambda x: np.average(x, weights=inter.loc[x.index, "area"]) #https://stackoverflow.com/questions/31521027/groupby-weighted-average-and-sum-in-pandas-dataframe
f = {price_column: {'weighted_mean' : wm} }
newdf = inter.groupby(zip_area_id_column).agg(f)
newdf.columns = newdf.columns.droplevel()

Then join/merge newdf back to the zip polygons if you want.

1415          142.841362
1439          285.705400
1440          372.325510
1442          388.012432
1444          319.763218
1445          464.308318
1462          273.379472
1485          256.614212
1487          189.018582
1488          353.688960
1489          268.873202
1494          240.251814

enter image description here


The BERA answer throws an error in new versions of python due to deprecated "dict-of-dict" approach. See https://stackoverflow.com/questions/60229375/solution-for-specificationerror-nested-renamer-is-not-supported-while-agg-alo.

I think BERA's code works if you change the last three lines of code to:

f = {price_column: wm} 
newdf = inter.groupby(zip_area_id_column).agg(f)
  • I dont post answers that doesn't work
    – BERA
    Apr 30, 2022 at 16:17

Your Answer

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

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