Wednesday, 8 June 2016

qgis - Sum values of a field based on unique values in another field?


I have a layer made of a field with repeted string values ("building") and a field with float values ("flatssurface"). I'd like to write a script to do some arithmetic operations (like sum, max and min, etc.) on all the values in column B which are associated to same values in column A but it doesn't work.



BUILDING       FLATSURF    SUM (wanted result)

1 40.0 115 (i.e. 40+45+30 m^2)
1 45.0 115
1 30.0 115
2 200.0 300 (i.e. 200+100 m^2)
2 100.0 300
3 60.0 140 (i.e. 60+80 m^2)
3 80.0 140


building=layer.dataProvider().fieldNameIndex('BUILDING')

flatssurface=layer.dataProvider().fieldNameIndex('FLATSURF')

uniquevalues=layer.uniqueValues(building,limit=10000)
for uv in uniquevalues:
feat=layer.getFeatures()
for f in feat:
tot=sum([flatssurface])
print tot

however it returns only the index of the field flats' surface (f[1]). For simplicity, I neglected the part on adding the field but I just tried to print the results, in order to check if it worked. If possible, I don't need answers related to GroupStats (Calculating sum of parts of column based on another column using QGIS Field Calculator?) or SQL or statistics (https://gis.stackexchange.com/editing-help) but I am looking only for solution related to Python.




Answer



when you do


flatssurface=layer.dataProvider().fieldNameIndex('FLATSURF')

you are indeeded getting the index (column number) of the field Flatsurf. To access the data, in your loop, you need to get the feature, its attributes, and at last restrict to the proper column using the index you have found. So, the numerical value you want to use in your loop is


f.attributes()[flatssurface]


On top of accessing the field value, you need to sum it by building. Using your sample code you are making the cross product of all buildings by all building values.


buildingidx=layer.dataProvider().fieldNameIndex('BUILDING')
flatssurfaceidx=layer.dataProvider().fieldNameIndex('FLATSURF')


uniquevalues=layer.uniqueValues(buildingidx,limit=10000)
for uv in uniquevalues:
#re-initialise the total area for each building
tot = 0.0

#statement for selecting just the proper buildings
exp = QgsExpression('BUILDING = ' + str(uv))
request = QgsFeatureRequest(exp)
#Select only the buildings having the specified value
feat=layer.getFeatures(request)

#Do the sum
for f in feat:
tot+=f.attributes()[flatssurfaceidx]
#once done, print the building value and the corresponding total surface
print("Building:",uv, "Total surface:", tot)

No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...