Adicionando campo e calculando expressão com PyQGIS?

10

Eu quero usar o PyQGIS para adicionar um novo campo e calcular os valores para cada recurso. Semelhante à opção Calculadora de campo.

Minha expressão 'Calculadora de campo' é, por exemplo: 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 é o erro que recebo:

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
fonte

Respostas:

11

O erro que você recebe diz que o índice do campo é -1, portanto, seu novo campo não foi encontrado na sua tabela de atributos.

Isso pode estar acontecendo porque:

  1. Você precisa usar em QVariant.Doublevez de QVariant.Float.
  2. Você não confirmou o novo campo ao provedor de camadas antes de solicitar seu novo índice de coluna.
  3. Você está solicitando o índice de, myNewColumnmas seu provedor pode armazenar apenas 10 caracteres para nomes de campos, portanto, ele foi armazenado myNewColum(final ausente n). (Aconteceu comigo enquanto tentava responder)

Tente isso:

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

Agora idxdeve ser diferente de -1, você pode verificá-lo:

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

A propósito, você pode executar o #step 1código fora do bloco de edição.

Germán Carrillo
fonte
11
Após alguns testes básicos, acho que é o limite de caracteres do nome do campo. É claro que enviar 'x coord' para um QVariant.Int também não é uma boa ideia, sem erros, apenas uma programação ruim. O dobro deve estar lá. graças
Ohto
Para ser sincero, é a primeira vez que enfrento esse problema. Como sempre, testar linha por linha fornece dicas sobre o que pode estar acontecendo.
Germán Carrillo