Добавить поле и вычислить выражение с помощью PyQGIS?

10

Я хочу использовать PyQGIS, чтобы добавить новое поле и рассчитать значения для каждой функции. Аналогично опции Калькулятор поля.

Мое выражение «Калькулятор поля», например: 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()

Это ошибка, которую я получаю:

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
источник

Ответы:

11

Полученная ошибка говорит о том, что индекс поля равен -1, поэтому ваше новое поле не найдено в таблице атрибутов.

Это может происходить потому что:

  1. Вам нужно использовать QVariant.Doubleвместо QVariant.Float.
  2. Вы не передали новое поле поставщику слоя перед тем, как запросить новый индекс столбца.
  3. Вы запрашиваете индекс, myNewColumnно ваш провайдер может хранить только 10 символов для имен полей, поэтому он сохранился myNewColum(отсутствует окончательный вариант n). (Просто случилось со мной, когда я попробовал ответить)

Попробуйте это вместо этого:

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

Теперь idxдолжно отличаться от того -1, что вы можете проверить:

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

Кстати, вы можете запустить #step 1код из блока редактирования.

Герман Каррильо
источник
1
После некоторого базового тестирования я думаю, что это предел символов имени поля. Конечно, отправка 'x координат' в QVariant.Int тоже не очень хорошая идея, но без ошибок, просто плохое программирование. Двойник должен быть там. спасибо
OHTO
Если честно, я впервые сталкиваюсь с такой проблемой. Как всегда, тестирование построчно дает вам подсказки о том, что может происходить.
Герман Каррильо