4

I am trying to calculate a unique ID field for a vector layer in qgis, using python. I found some code to calculate attribute values, and tried to increment the value in the expression, but it doesn't work - it calculates all feature values as 0. I'm guessing the intial value I set for the expression is what it is reading each time - it doesn't seem to change it inside the loop. Anyone have any ideas? Here is my code:

QgsMapLayerRegistry.instance().addMapLayer(dsslvExplodeLyr)

idx = dsslvExplodeLyr.fieldNameIndex('UniqueID')

eVal = '0'
e = QgsExpression(eVal)
e.prepare(dsslvExplodeLyr.pendingFields())

dsslvExplodeLyr.startEditing()

for f in dsslvExplodeLyr.getFeatures():
    num = int(eVal)
    num = num + 1
    eVal = str(num)     
    f[idx] = e.evaluate(f)
    dsslvExplodeLyr.updateFeature(f)

dsslvExplodeLyr.commitChanges()

I should mention I've also tried '$rownum' for the expression as that works in the field calculator gui but it also just gives a value of 0.

3

I'm not sure how that was going to work with the str(num) and int(eVal), it seems to me that the values are being overwritten on each iteration. Try it this way:

QgsMapLayerRegistry.instance().addMapLayer(dsslvExplodeLyr)

idx = dsslvExplodeLyr.fieldNameIndex('UniqueID')

eVal = '0'
num = 0
e = QgsExpression(eVal) # where does 'e' come into it? leaving it here because it may have other uses (undisclosed)
e.prepare(dsslvExplodeLyr.pendingFields())

dsslvExplodeLyr.startEditing()

for f in dsslvExplodeLyr.getFeatures():
    eVal = str(num)  #I'm assuming that the field 'UniqueID' is a string, isn't it?   
    f.setAttribute(idx,eVal) # set the value for the field, aslo works with field name
    dsslvExplodeLyr.updateFeature(f)
    num += 1 # post iterate, so the first is 0, second is 1 and so on.

dsslvExplodeLyr.commitChanges()
  • thanks for the reply, i see I had the num = num + 1 in the wrong place. The field is an integer field actually, though it seems my expression has to be a string? I'm new with this.. I'll test this out – kflaw Mar 9 '15 at 21:48
  • If your field is an integer then use f.setAttribute(idx,num) and take eVal out altogether (the type is const QVariant, so the function will take string, double, int, float..). The problem was you were overwriting the value to be incremented each time and not applying it to the field, regardless of the value. – Michael Stimson Mar 9 '15 at 21:53
  • I got QgsExpression code from another example but looks like it's not necessary – kflaw Mar 10 '15 at 14:45
  • It looks like the QgsExpression is the QGIS equivalent of the code block in Esri Calculate Field. For a simple calculation (f.setAttribute(field,KnownValue)) I'd say it's not necessary but gives the ability to call other fields and derive values from them with a complex statement - definitely one to remember for the future. – Michael Stimson Mar 10 '15 at 21:15
4

This code works well (fillFields function) and it is not requiered the start editing operating.

def fillFields(list, idx):
    i =0
    for item in list:
        new_values = {idx:item }
        provider.changeAttributeValues({i: new_values})
        i += 1

from PyQt4.QtCore import *

dsslvExplodeLyr = iface.activeLayer()

provider = dsslvExplodeLyr.dataProvider()

idx = dsslvExplodeLyr.fieldNameIndex('UniqueID')

n= dsslvExplodeLyr.featureCount()  #count features

field1 = range(n)   #create list with n values

fillFields(field1, idx)  #introduce list 'field1' in field with index of 'UniqueID'

I used your nomenclature for the layer name (dsslvExplodeLyr; a point vector layer) and its field name (UniqueID). The script changed aleatory values between -10 and 10 into this field to integer values between 0-24.

Before running the code in the Python Console:

enter image description here

After running the code

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.