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:
- Find all categories for the building data [define CATEGORYFIELD]
- Loop through each category and select the matching buildings
- Assign the Stats to the input Grid Layer [define what to summarize and how: FIELDS / SUMS]
- Load each Grid Layer with category stats to the map
#VARIABLES/ CHNAGE THESE
GRID = '.../GRID.gpkg'
BUILDINGS='../Buildings.gpkg'
CATEGORYFIELD = 'zone_code_'
#summary fields:
FIELDS=['area','roof_heigh']
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
'PREDICATE':0, #USE SELECTED FEATURES
'JOIN_FIELDS':FIELDS,
'SUMMARIES':SUMS,
'DISCARD_NONMATCHING':False,
#'OUTPUT':'C:/temp/DeleteMe/test1.shp'}
'OUTPUT':'%s%s.shp'%(OUTPUT_FOLDER,val)}
#RUN ANALYSIS (join by location summary) on selection only
result = processing.runAndLoadResults("qgis:joinbylocationsummary", params)
print('FINISHED FOR: %s'%val)
#remove selection / reset:
bldlayer.removeSelection()