¿Agregar campo y calcular expresión con PyQGIS?

10

Quiero usar PyQGIS para agregar un nuevo campo y calcular los valores para cada característica. Similar a la opción Calculadora de campo.

Mi expresión 'Calculadora de campo' es, por ejemplo: 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()

Este es el error que obtengo:

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'
OHTO
fuente

Respuestas:

11

El error que obtiene dice que el índice de campo es -1, por lo que su nuevo campo no se encontró en su tabla de atributos.

Eso puede estar sucediendo porque:

  1. Necesitas usar en QVariant.Doublelugar de QVariant.Float.
  2. No ha confirmado el nuevo campo al proveedor de capas antes de solicitar su nuevo índice de columna.
  3. Está solicitando el índice de, myNewColumnpero su proveedor solo puede almacenar 10 caracteres para los nombres de campo, por lo que se ha almacenado myNewColum(falta el final n). (Solo me sucedió mientras intentaba la respuesta)

Intenta esto en su lugar:

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

Ahora idxdebería ser diferente a -1, puedes verificarlo:

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

Por cierto, puede ejecutar el #step 1código fuera del bloque de edición.

Germán Carrillo
fuente
1
Después de algunas pruebas básicas, creo que es el límite de caracteres del nombre del campo. Por supuesto, enviar 'x coord' a un QVariant. No es una buena idea también, no hay error, solo una mala programación. El doble debería estar allí. gracias
OHTO
Para ser honesto, es la primera vez que enfrento ese problema. Como siempre, probar línea por línea te da pistas sobre lo que podría estar sucediendo.
Germán Carrillo