2

In PyQGIS can I get the total length of a road where it's broken up into segments?

In SQL I would run

SELECT 
 format_number(ROAD_ID,0) as Road_ID,
 ROAD_NAME as Road,
 format_number(Sum(st_length(geometry)),2) as Total,
 Count(*) as Segment_Count
FROM
 CSC_Roads
GROUP BY Road, Owner
ORDER BY Owner, Road

For each segment I do have GIS_Length which is just $length but how would I do a aggregate sum when the RoadMntnc name is the same so that for each road segment we have the Total_length and Segment_length.

Would the best solution be something like?

geom=f.geometry()
ntext=to_string(format_number(sum(geom.length(),group_by:="RoadMntnc"),0))

I keep getting invalid syntax on the above

In field calc the following works - to_string(format_number(sum($length,group_by:="RoadMntnc"),0))

==== The complete code is

import re

def Update_Field(fieldName, ntext): # Function to simplify updating fields
    print (ntext)
    fieldIndex = layer.fields().indexFromName(fieldName)
    dpr.changeAttributeValues({f.id(): {fieldIndex: ntext}})
    layer.commitChanges()

RoadType_dict = {'Rd':'Road', 'Avenue': 'Ave'}
layer = iface.activeLayer()
selection = layer.getFeatures() #all features
#selection = layer.selectedFeatures() #only selected features

#Locality Data
Locality_layer=QgsVectorLayer(r'Z:\My Drive\Mangoesmapping\Spatial Projects\Gen_Library\DSC\vector\DSC_Localities_areas.shp', "Locality", "ogr")

dpr = layer.dataProvider()

for f in selection:
    print (f.id())
    text=f['RoadMntnc']
    print (text)
    stext=re.split('_+', text)
##Update RoadName
#    ntext=' '.join(stext[:-1])
#    fieldName='RoadName'
#    Update_Field(fieldName,ntext)
##Update Road Type Abbreviation
#    ntext=stext[-1:][0]
#    fieldName='Type_Abb'
#    Update_Field(fieldName,ntext)
##Update Road Type
#    ntext=RoadType_dict.get(stext[-1:][0])
#    fieldName='Type'
#    Update_Field(fieldName,ntext)
##Update Road Length
    geom=f.geometry()
    ntext=to_string(format_number(sum(geom.length(),group_by:="RoadMntnc"),0))
    fieldName='Chainage'
    Update_Field(fieldName,ntext)

layer.commitChanges()
layer.updateFields()
GeorgeC
  • 8,228
  • 7
  • 52
  • 136

1 Answers1

2

Perhaps you could make use of the QgsExpression Class:

##Update Road Length
    e = QgsExpression( ' to_string(format_number(sum($length,group_by:="RoadMntnc"),0)) ' )
    fieldName='Chainage'
    f[fieldName] = e.evaluate()
    layer.updateFeature(f)
Joseph
  • 75,746
  • 7
  • 171
  • 282
  • 1
    Works great -thank you. Would this strategy work to address the following question as well? https://gis.stackexchange.com/questions/331477/pyqgis-update-field-in-line-dataset-when-it-is-within-a-polygon – GeorgeC Aug 09 '19 at 12:29
  • @GeorgeC - Most welcome, glad it helped! I don't see why it shouldn't work. Maybe an expression like e = QgsExpression(geomwithin('targetLayer','TargetField') where you replace targetLayer for the name of the layer and TargetField for the field you're interested in? – Joseph Aug 09 '19 at 12:36