I have written a python script in QGIS which estimates the amount of residents for each building polygon by using census block data and building polygons (about 500 000 buildings in an area of about 900 km2).
The relevant data from the census blocks was merged to the building layer, so only the building layer is used in the script to collect the data. It has the following fields:
| A_building | id_census | pop_census_block |
The steps of the script are:
- Sort buildings by id_census
- Sum all building footprint areas for each census block
- Calculate the areal share and from that the amount of residents for each footprint.
- Update 2 attributes of the feature (
The 3rd and 4th step happen in a loop, that iterates over each building polygon. This loop takes two days, which seems to me too long for such a simple operation. Is there a faster way to update the features of a layer, like sending the calculated data as a list?
Here is the relevant section in the script:
# feats is a python list: feats = [feat for feat in layer.getFeatures(QgsFeatureRequest().setFlags(QgsFeatureRequest.NoGeometry).setSubsetOfAttributes(limit_cols)) ] # sort feats feats.sort(key=itemgetter(col_census_id)) ... # Get unique census ids census_ids =  areas = dict() for feat in feats: census_id = feat[col_census_id] if census_id not in census_ids: census_ids.append(census_id) areas[census_id] = 0 # Sum building area per census block for i in range(len(feats)): # Sum area census_id = feats[i][col_census_id] areas[census_id] += feats[i][col_bldg_area] # Start an undo block layer.beginEditCommand('Calculate share of area') i, j, k = 0, 0, 0 layer.startEditing() for feat in feats: # Share of area share = feat[col_bldg_area] / float(areas[feat[col_census_id]]) # Add share to feature feat[col_share] = share # Building population feat[col_bldg_pop] = int(feat[col_pop] * feat[col_share]) layer.updateFeature(feat) ... # End the undo block layer.endEditCommand() # Comit changes layer.commitChanges() return layer