I have a vector which contain thousands of buildings of different categories (e.g., residential, office) and a regular sized grid cell vector (but can also convert to raster).

I would like to perform zonal statistics of the buildings attributes that are inside each grid cell, while accounting for the different categories.

The result would produce, for each grid cell, for each different building category, the mean and variance of some attributes (e.g., height and area).

Any suggestions on how to tackle that on QGis?


1 Answer 1


We can do this by selecting the building by category and then running join attributes by location (summary)

For each cateogory type in the input building layer, we will have a resulting summarized vector grid layer.

The following code will do the following:

  1. Find all categories for the building data [define CATEGORYFIELD]
  2. Loop through each category and select the matching buildings
  3. Assign the Stats to the input Grid Layer [define what to summarize and how: FIELDS / SUMS]
  4. Load each Grid Layer with category stats to the map
GRID = '.../GRID.gpkg'
CATEGORYFIELD = 'zone_code_'
#summary fields:
SUMS = [2,3,6,8]
OUTPUT_FOLDER = "C:/temp/"

#layer = iface.activeLayer()
gridlayer = iface.addVectorLayer(GRID, "buildings", "ogr")
bldlayer= iface.addVectorLayer(BUILDINGS, "buildings", "ogr")

#get all possible values for category fields
idx = bldlayer.fields().indexOf('%s'%CATEGORYFIELD)
values = bldlayer.uniqueValues(idx)

#run analysis for each category, make selection based on category each run
for val in values:
    #make slection based on value:
    bldlayer.selectByExpression('"%s"=\'%s\'' %(CATEGORYFIELD,val))     
    #clean special character from value
    val = ''.join(filter(str.isalnum, val))
    print ('\nRUNNING FOR:%s'%val)
    # Set input params
    params = {'INPUT':gridlayer,
              'JOIN':QgsProcessingFeatureSourceDefinition(bldlayer.id(), True), # USE HERE THE SELECTED FEATURES
    #RUN ANALYSIS (join by location summary) on selection only
    result = processing.runAndLoadResults("qgis:joinbylocationsummary", params)
    print('FINISHED FOR: %s'%val)
    #remove selection / reset:
  • Thank you! That did the job! May 2, 2023 at 7:00

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.