Monday, 15 January 2018

Adding field and calculating expression with PyQGIS?


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 "", line 1, in
File "/var/folders/0r/q6nxg6w54fv4l7c8gksb2t500000gn/T/tmp9dosIe.py", line 30, in
f[idx] = e.evaluate( f )
KeyError: '-1'

Answer



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.


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...