2

I want to calculate the values for each feature using python.

First I added a new field and it worked excellently (Adding field and calculating expression with PyQGIS?).

Now I want to calculate an Expression

Here is my code

from PyQt4.QtCore import QVariant
from qgis.core import QgsField, QgsExpression, QgsFeature

#add new field
myField = QgsField ('eur1_km2', QVariant.Double)
layer.startEditing()
layer.dataProvider().addAttributes([myField])
layer.updateFields()
idx = layer.dataProvider().fieldNameIndex('eur1_km2')

#calculating values for myField
e = QgsExpression( '[SHAPE_Area]/1000000*6' )

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

layer.commitChanges()

The "SHAPE_Area" is a Field within the attribute table with different values. It is in square metres.

How can I call the values for "SHAPE_Area", so it can be calculated?


I'm using QGIS 3.0 for this dataProvider() is necessary, otherwise an error occurs.

idx = layer.fieldNameIndex('eur1_km2')
Traceback (most recent call last):
  File "C:\PROGRA~1\QGIS3~1.0\apps\Python36\lib\code.py", line 91, in runcode
    exec(code, self.locals)
  File "<input>", line 1, in <module>
AttributeError: 'QgsVectorLayer' object has no attribute 'fieldNameIndex'

The next is, that in QGIS 3.0 pendingFields() does not longer exists. An error occurs

e.prepare(layer.pendingFields())
Traceback (most recent call last):
  File "C:\PROGRA~1\QGIS3~1.0\apps\Python36\lib\code.py", line 91, in runcode
    exec(code, self.locals)
  File "<input>", line 1, in <module>
AttributeError: 'QgsVectorLayer' object has no attribute 'pendingFields'

Last point another error arise for the last part

for f in layer.getFeatures():
    f[idx] = e.evaluate( f )
    layer.updateFeature( f )
Traceback (most recent call last):
  File "C:\PROGRA~1\QGIS3~1.0\apps\Python36\lib\code.py", line 91, in runcode
    exec(code, self.locals)
  File "<input>", line 2, in <module>
TypeError: QgsExpression.evaluate(): arguments did not match any overloaded call:
  overload 1: too many arguments
  overload 2: argument 1 has unexpected type 'QgsFeature'

So, is there an other method for calling the attribute values?

etrimaille
  • 7,240
  • 34
  • 47
Helga F.
  • 365
  • 2
  • 13

2 Answers2

2

You can remove the square brackets in your expression and replace them with double quotes (or nothing):

e = QgsExpression( '"SHAPE_Area"/(1000000*6)')

You may also need to use the prepare() and evaluate methods when calculating values with QgsExpression:

e = QgsExpression( '"SHAPE_Area"/(1000000*6)')
e.prepare(layer.pendingFields())

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

You can also avoid having to call the dataProvider() and add the field and obtain the field index directly:

layer.addAttribute(myField)
layer.updateFields()
idx = layer.fieldNameIndex('eur1_km2')

So your code could look something like:

from PyQt4.QtCore import QVariant
from qgis.core import QgsField, QgsExpression, QgsFeature

#add new field
myField = QgsField('eur1_km2', QVariant.Double)
layer.startEditing()
layer.addAttribute(myField)
layer.updateFields()
idx = layer.fieldNameIndex('eur1_km2')

#calculating values for myField
e = QgsExpression( '"SHAPE_Area"/(1000000*6)')
e.prepare(layer.pendingFields())

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

layer.commitChanges()
Joseph
  • 75,746
  • 7
  • 171
  • 282
1

I solved the problem on my own. This is the code which I'm using with QGIS 3.0.1:

#add new field
myField = QgsField ('eur1_km2', QVariant.Double)
layer.startEditing()
layer.dataProvider().addAttributes([myField])
layer.updateFields()
idx = layer.dataProvider().fieldNameIndex('eur1_km2')

#calculate new values
for f in layer.getFeatures():
    sa = layer.dataProvider().fieldNameIndex('SHAPE_Area')
    attr_sa = f.attributes()[sa]
    f[idx] = (attr_sa/1000000*6)
    layer.updateFeature( f )

layer.commitChanges()
PolyGeo
  • 65,136
  • 29
  • 109
  • 338
Helga F.
  • 365
  • 2
  • 13