The code snippets on this page needs the following imports if you’re outside the pyqgis console:
from qgis.core import (
edit,
QgsExpression,
QgsExpressionContext,
QgsFeature,
QgsFeatureRequest,
QgsField,
QgsFields,
QgsVectorLayer,
QgsPointXY,
QgsGeometry,
QgsProject,
QgsExpressionContextUtils
)
표현식을 이용한 속성값의 필터링 및 계산¶
QGIS has some support for parsing of SQL-like expressions. Only a small subset of SQL syntax is supported. The expressions can be evaluated either as boolean predicates (returning True or False) or as functions (returning a scalar value). See 표현식 in the User Manual for a complete list of available functions.
다음 3가지 기본 유형이 지원됩니다.
숫자 — 정수와 십진수, 예를 들면
123
,3.14
문자열 —
'hello world'
처럼 작은 따옴표로 둘러싸야 함컬럼 참조 — 표현식을 평가할 때, 참조가 필드의 실제 값으로 대체됩니다. 이름이 그대로 남지 않습니다.
다음과 같은 연산자들이 있습니다.
산술 연산자:
+
,-
,*
,/
,^
괄호:
(1 + 1) * 3
처럼 연산의 우선 순위를 강제합니다.단항 플러스 및 마이너스:
-12
,+5
수학 함수:
sqrt
,sin
,cos
,tan
,asin
,acos
,atan
conversion functions:
to_int
,to_real
,to_string
,to_date
도형 함수:
$area
,$length
geometry handling functions:
$x
,$y
,$geometry
,num_geometries
,centroid
다음과 같은 서술어들를 지원합니다.
비교:
=
,!=
,>
,>=
,<
,<=
패턴 매칭:
LIKE
(%
와_
사용),~
(정규 표현식)논리 술어:
AND
,OR
,NOT
NULL 값 확인:
IS NULL
,IS NOT NULL
서술어의 예:
1 + 2 = 3
sin(angle) > 0
'Hello' LIKE 'He%'
(x > 10 AND y > 10) OR z = 0
스칼라 표현식의 예:
2 ^ 10
sqrt(val)
$length + 1
표현식 파싱하기¶
The following example shows how to check if a given expression can be parsed correctly:
exp = QgsExpression('1 + 1 = 2')
assert(not exp.hasParserError())
exp = QgsExpression('1 + 1 = ')
assert(exp.hasParserError())
assert(exp.parserErrorString() == '\nsyntax error, unexpected $end')
표현식 평가하기¶
Expressions can be used in different contexts, for example to filter features or to compute new field values. In any case, the expression has to be evaluated. That means that its value is computed by performing the specified computational steps, which can range from simple arithmetic to aggregate expressions.
기본 표현식¶
This basic expression evaluates to 1, meaning it is true:
exp = QgsExpression('1 + 1 = 2')
assert(exp.evaluate())
피처와 표현식¶
To evaluate an expression against a feature, a QgsExpressionContext
object has to be created and passed to the evaluate function in order to allow the expression to access
the feature’s field values.
The following example shows how to create a feature with a field called 《Column》 and how to add this feature to the expression context.
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)
The following is a more complete example of how to use expressions in the context of a vector layer, in order to compute new field values:
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'])
Filtering a layer with expressions¶
다음 예시 코드는 레이어를 필터링해서 서술어와 일치하는 모든 피처를 반환하는 작업에 사용할 수 있습니다.
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)
Handling expression errors¶
Expression-related errors can occur during expression parsing or evaluation:
exp = QgsExpression("1 + 1 = 2")
if exp.hasParserError():
raise Exception(exp.parserErrorString())
value = exp.evaluate()
if exp.hasEvalError():
raise ValueError(exp.evalErrorString())