Los fragmentos de código en esta página necesitan las siguientes adiciones si está fuera de la consola de pyqgis:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
from qgis.core import (
    edit,
    QgsExpression,
    QgsExpressionContext,
    QgsFeature,
    QgsFeatureRequest,
    QgsField,
    QgsFields,
    QgsVectorLayer,
    QgsPointXY,
    QgsGeometry,
    QgsProject,
    QgsExpressionContextUtils
)

11. Expresiones, Filtros y Calculando Valores

QGIS tiene apoyo para el análisis de expresiones parecidas al SQL. Solo se reconoce un pequeño subconjunto de sintaxis SQL. Las expresiones pueden ser evaluados ya sea como predicados booleanos (regresando Verdadero o Falso ) o como funciones (regresando un valor escalar). Vea Expresiones en el Manual del usuario para obtener una lista completa de las funciones disponibles.

Se le da apoyo a tres tipos:

  • numero - números enteros y números con decimales, e.j. 123, 3.14

  • cadena - se tiene que encerrar en comas individuales: 'hola mundo'

  • columna de referencia - cuando se evalúa, la referencia se substituye con el valor actual del campo. Los nombres no se escapan.

Los siguientes operadores están disponibles:

  • operadores aritméticos: «+». «-«, «/», ^

  • paréntesis: para hacer cumplir la precedencia del operador: (1 + 1) * 3

  • unario mas y menos: -12, +5

  • funciones matemáticas: sqrt, sin, cos, tan, asin, acos, atan

  • funciones de conversión: to_int, to_real, to_string, to_date

  • funciones geométricas: $area, $length

  • funciones de manejo de geometría: $x, $y, $geometry, num_geometries, centroid

Se apoya las siguientes predicciones:

  • comparación: =, !=, >, >=, <, <=

  • patrones iguales: LIKE (using % and _), ~ (expresión regular)

  • lógica predicado: AND, OR, NOT

  • revisión de valores NULO: IS NULL, IS NOT NULL

Ejemplos de predicado:

  • 1 + 2 = 3

  • sin(angulo) > 0

  • “Hello” LIKE “He%”`

  • (x > 10 AND y > 10) OR z = 0

Ejemplo de escala de expresiones:

  • 2 ^ 10

  • sqrt(val)

  • $length + 1

11.1. Análisis de expresiones

El siguiente ejemplo muestra cómo verificar si una expresión dada se puede analizar correctamente:

1
2
3
4
5
6
7
exp = QgsExpression('1 + 1 = 2')
assert(not exp.hasParserError())

exp = QgsExpression('1 + 1 = ')
assert(exp.hasParserError())

assert(exp.parserErrorString() == '\nsyntax error, unexpected $end')

11.2. Evaluar expresiones

Las expresiones se pueden usar en diferentes contextos, por ejemplo, para filtrar entidades o para calcular nuevos valores de campo. En cualquier caso, la expresión tiene que ser evaluada. Eso significa que su valor se calcula realizando los pasos computacionales especificados, que pueden variar desde expresiones aritméticas simples hasta expresiones agregadas.

11.2.1. Expresiones Basicas

Esta expresión básica se evalúa a 1, lo que significa que es cierto:

exp = QgsExpression('1 + 1 = 2')
assert(exp.evaluate()) # exp.evaluate() returns 1 and assert() recognizes this as True

11.2.2. Expresiones con caracteristicas

Para evaluar una expresión sobre una entidad, se debe crear un objeto :clase:`QgsExpressionContext <qgis.core.QgsExpressionContext>` y pasarlo a la función de evaluación para permitir que la expresión acceda a los valores de campo de la entidad.

El siguiente ejemplo muestra cómo crear una entidad con un campo llamado «Columna» y cómo agregar esta entidad al contexto de expresión.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
fields = QgsFields()
field = QgsField('Column')
fields.append(field)
feature = QgsFeature()
feature.setFields(fields)
feature.setAttribute(0, 99)

exp = QgsExpression('"Column"')
context = QgsExpressionContext()
context.setFeature(feature)
assert(exp.evaluate(context) == 99)

El siguiente es un ejemplo más completo de cómo usar expresiones en el contexto de una capa vectorial, para calcular nuevos valores de campo:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
from qgis.PyQt.QtCore import QVariant

# create a vector layer
vl = QgsVectorLayer("Point", "Companies", "memory")
pr = vl.dataProvider()
pr.addAttributes([QgsField("Name", QVariant.String),
                  QgsField("Employees",  QVariant.Int),
                  QgsField("Revenue", QVariant.Double),
                  QgsField("Rev. per employee", QVariant.Double),
                  QgsField("Sum", QVariant.Double),
                  QgsField("Fun", QVariant.Double)])
vl.updateFields()

# add data to the first three fields
my_data = [
    {'x': 0, 'y': 0, 'name': 'ABC', 'emp': 10, 'rev': 100.1},
    {'x': 1, 'y': 1, 'name': 'DEF', 'emp': 2, 'rev': 50.5},
    {'x': 5, 'y': 5, 'name': 'GHI', 'emp': 100, 'rev': 725.9}]

for rec in my_data:
    f = QgsFeature()
    pt = QgsPointXY(rec['x'], rec['y'])
    f.setGeometry(QgsGeometry.fromPointXY(pt))
    f.setAttributes([rec['name'], rec['emp'], rec['rev']])
    pr.addFeature(f)

vl.updateExtents()
QgsProject.instance().addMapLayer(vl)

# The first expression computes the revenue per employee.
# The second one computes the sum of all revenue values in the layer.
# The final third expression doesn’t really make sense but illustrates
# the fact that we can use a wide range of expression functions, such
# as area and buffer in our expressions:
expression1 = QgsExpression('"Revenue"/"Employees"')
expression2 = QgsExpression('sum("Revenue")')
expression3 = QgsExpression('area(buffer($geometry,"Employees"))')

# QgsExpressionContextUtils.globalProjectLayerScopes() is a convenience
# function that adds the global, project, and layer scopes all at once.
# Alternatively, those scopes can also be added manually. In any case,
# it is important to always go from “most generic” to “most specific”
# scope, i.e. from global to project to layer
context = QgsExpressionContext()
context.appendScopes(QgsExpressionContextUtils.globalProjectLayerScopes(vl))

with edit(vl):
    for f in vl.getFeatures():
        context.setFeature(f)
        f['Rev. per employee'] = expression1.evaluate(context)
        f['Sum'] = expression2.evaluate(context)
        f['Fun'] = expression3.evaluate(context)
        vl.updateFeature(f)

print( f['Sum'])
876.5

11.2.3. Flitrando una capa con expresiones

El siguiente ejemplo se puede utilizar para filtra capas y regresar cualquier característica que empata con el predicado.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
layer = QgsVectorLayer("Point?field=Test:integer",
                           "addfeat", "memory")

layer.startEditing()

for i in range(10):
    feature = QgsFeature()
    feature.setAttributes([i])
    assert(layer.addFeature(feature))
layer.commitChanges()

expression = 'Test >= 3'
request = QgsFeatureRequest().setFilterExpression(expression)

matches = 0
for f in layer.getFeatures(request):
   matches += 1

assert(matches == 7)

11.3. Manejando errores de expresión

Los errores relacionados con la expresión pueden ocurrir durante el análisis o la evaluación de expresiones:

1
2
3
4
5
6
7
exp = QgsExpression("1 + 1 = 2")
if exp.hasParserError():
   raise Exception(exp.parserErrorString())

value = exp.evaluate()
if exp.hasEvalError():
   raise ValueError(exp.evalErrorString())