8

I want to use PyQGIS to add a new field and calculate the values for each feature. Similar to Field Calculator option.

My 'Field Calculator' expression is for example: y(start_point($geometry))

from PyQt4.QtCore import QVariant
from qgis.core import QgsField, QgsExpression, QgsFeature
vl = iface.activeLayer()

vl.startEditing()

#step 1
myField = QgsField( 'myNewColumn', QVariant.Float )
vl.addAttribute( myField )
idx = vl.fieldNameIndex( 'myNewColumn' )

#step 2
e = QgsExpression( 'y(start_point($geometry))' )
e.prepare( vl.pendingFields() )

for f in vl.getFeatures():
    f[idx] = e.evaluate( f )
    vl.updateFeature( f )

vl.commitChanges()

This is the error I get:

Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "/var/folders/0r/q6nxg6w54fv4l7c8gksb2t500000gn/T/tmp9dosIe.py", line 30, in <module>
    f[idx] = e.evaluate( f )
KeyError: '-1'
8

The error you get says the field index is -1, so your new field wasn't found in your attribute table.

That may be happening because:

  1. You need to use QVariant.Double instead of QVariant.Float.
  2. You've not committed the new field to the layer provider before asking for your new column index.
  3. You're asking for the index of myNewColumn but your provider can only store 10 characters for field names, so it has stored myNewColum (missing final n). (Just happened to me while giving the answer a try)

Try this instead:

#step 1
myField = QgsField( 'newColumn', QVariant.Double )
vl.dataProvider().addAttributes([myField])
vl.updateFields()
idx = vl.fieldNameIndex( 'newColumn' )

Now idx should be different than -1, you can check it:

if idx != -1:
    print "Field found!"

By the way, you can run the #step 1 code out of the edit block.

  • 1
    After some basic testing I think its the character limit of the field name. Of course sending 'x coord' to an QVariant.Int isn't a good idea too, no error though, just bad programming. Double should be there. thanks – OHTO Jun 9 '16 at 14:22
  • To be honest, it's the first time I face such problem. As always, testing line by line gives you hints on what might be happening. – Germán Carrillo Jun 9 '16 at 14:25

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.