重要
翻訳は あなたが参加できる コミュニティの取り組みです。このページは現在 100.00% 翻訳されています。
11. 式、フィルタ適用および値の算出
ヒント
pyqgisコンソールを使わない場合、このページにあるコードスニペットは次のインポートが必要です:
1from qgis.core import (
2 edit,
3 QgsExpression,
4 QgsExpressionContext,
5 QgsFeature,
6 QgsFeatureRequest,
7 QgsField,
8 QgsFields,
9 QgsVectorLayer,
10 QgsPointXY,
11 QgsGeometry,
12 QgsProject,
13 QgsExpressionContextUtils
14)
QGISは、SQLに似た式の解析を一部サポートしています。SQL構文の小さなサブセットのみがサポートされています。式は、ブール述語( True または False を返す)または関数(スカラー値を返す)として評価することができます。利用できる関数の完全なリストについては、ユーザーマニュアルの 式 を参照してください。
3つの基本的な型がサポートされています。
数 --- 整数および小数。例.
123,3.14文字列 --- 一重引用符で囲む必要があります:
'hello world'列参照 --- 評価する際に、参照はフィールドの実際の値で置き換えられます。名前はエスケープされません。
次の演算子が利用可能です:
算術演算子:
+,-,*,/,^丸括弧: 演算を優先します:
(1 + 1) * 3単項のプラスとマイナス:
-12,+5数学的関数:
sqrt,sin,cos,tan,asin,acos,atan変換関数:
to_int、to_real、to_string、to_dateジオメトリ関数:
$area,$lengthジオメトリ処理関数:
$x、$y、$geometry、num_geometries、centroid
以下の述語がサポートされています:
比較:
=,!=,>,>=,<,<=パターンマッチング:
LIKE(% と _ を使用),~(正規表現)論理述語:
AND,OR,NOTNULL 値チェック:
IS NULL,IS NOT NULL
述語の例:
1 + 2 = 3sin(angle) > 0'Hello' LIKE 'He%'(x > 10 AND y > 10) OR z = 0
スカラー式の例:
2 ^ 10sqrt(val)$length + 1
11.1. 式を構文解析する
与えられた式が正しくパースできるかどうかは、以下の例で示す方法で確認します。
1exp = QgsExpression('1 + 1 = 2')
2assert(not exp.hasParserError())
3
4exp = QgsExpression('1 + 1 = ')
5assert(exp.hasParserError())
6
7assert(exp.parserErrorString() == '\nsyntax error, unexpected end of file')
11.2. 式を評価する
式は、例えば地物をフィルタしたり、新しいフィールド値を計算するなど、異なったコンテクストで使うことができます。いずれの場合においても、式は評価されなければなりません。つまり式の値は、単純な算術式から集約式まで、指定された計算ステップを実行することによって計算されます。
11.2.1. 基本的な式
この基本的な式は単純な算術演算を評価します:
exp = QgsExpression('2 * 3')
print(exp)
print(exp.evaluate())
<QgsExpression: '2 * 3'>
6
式は比較にも使用でき、1 (True) か 0 (False) かを評価します
exp = QgsExpression('1 + 1 = 2')
exp.evaluate()
# 1
11.2.2. 地物に関わる式
地物に関わる式を評価するためには、式が地物のフィールド値にアクセスできるようにするために、 QgsExpressionContext オブジェクトを生成し、評価関数に渡さなければなりません。
以下の例は、"Column" という名前のフィールドを持つ地物を作り、この地物を式のコンテクストに加える方法を示しています。
1fields = QgsFields()
2field = QgsField('Column')
3fields.append(field)
4feature = QgsFeature()
5feature.setFields(fields)
6feature.setAttribute(0, 99)
7
8exp = QgsExpression('"Column"')
9context = QgsExpressionContext()
10context.setFeature(feature)
11exp.evaluate(context)
12# 99
以下の例は、ベクターレイヤのコンテクストにおいて、新しいフィールド値を計算するためにどのように式を使うかを示す、より完成された例です。
1from qgis.PyQt.QtCore import QMetaType
2
3# create a vector layer
4vl = QgsVectorLayer("Point", "Companies", "memory")
5pr = vl.dataProvider()
6pr.addAttributes([QgsField("Name", QMetaType.Type.QString),
7 QgsField("Employees", QMetaType.Type.Int),
8 QgsField("Revenue", QMetaType.Type.Double),
9 QgsField("Rev. per employee", QMetaType.Type.Double),
10 QgsField("Sum", QMetaType.Type.Double),
11 QgsField("Fun", QMetaType.Type.Double)])
12vl.updateFields()
13
14# add data to the first three fields
15my_data = [
16 {'x': 0, 'y': 0, 'name': 'ABC', 'emp': 10, 'rev': 100.1},
17 {'x': 1, 'y': 1, 'name': 'DEF', 'emp': 2, 'rev': 50.5},
18 {'x': 5, 'y': 5, 'name': 'GHI', 'emp': 100, 'rev': 725.9}]
19
20for rec in my_data:
21 f = QgsFeature()
22 pt = QgsPointXY(rec['x'], rec['y'])
23 f.setGeometry(QgsGeometry.fromPointXY(pt))
24 f.setAttributes([rec['name'], rec['emp'], rec['rev']])
25 pr.addFeature(f)
26
27vl.updateExtents()
28QgsProject.instance().addMapLayer(vl)
29
30# The first expression computes the revenue per employee.
31# The second one computes the sum of all revenue values in the layer.
32# The final third expression doesn’t really make sense but illustrates
33# the fact that we can use a wide range of expression functions, such
34# as area and buffer in our expressions:
35expression1 = QgsExpression('"Revenue"/"Employees"')
36expression2 = QgsExpression('sum("Revenue")')
37expression3 = QgsExpression('area(buffer($geometry,"Employees"))')
38
39# QgsExpressionContextUtils.globalProjectLayerScopes() is a convenience
40# function that adds the global, project, and layer scopes all at once.
41# Alternatively, those scopes can also be added manually. In any case,
42# it is important to always go from “most generic” to “most specific”
43# scope, i.e. from global to project to layer
44context = QgsExpressionContext()
45context.appendScopes(QgsExpressionContextUtils.globalProjectLayerScopes(vl))
46
47with edit(vl):
48 for f in vl.getFeatures():
49 context.setFeature(f)
50 f['Rev. per employee'] = expression1.evaluate(context)
51 f['Sum'] = expression2.evaluate(context)
52 f['Fun'] = expression3.evaluate(context)
53 vl.updateFeature(f)
54
55print(f['Sum'])
876.5
11.2.3. 式を使ってレイヤをフィルタする
次の例はレイヤーをフィルタリングして述語に一致する任意の地物を返します。
1layer = QgsVectorLayer("Point?field=Test:integer",
2 "addfeat", "memory")
3
4layer.startEditing()
5
6for i in range(10):
7 feature = QgsFeature()
8 feature.setAttributes([i])
9 assert(layer.addFeature(feature))
10layer.commitChanges()
11
12expression = 'Test >= 3'
13request = QgsFeatureRequest().setFilterExpression(expression)
14
15matches = 0
16for f in layer.getFeatures(request):
17 matches += 1
18
19print(matches)
7
11.3. 式エラーを扱う
式をパースする過程、もしくは式を評価する過程で、式に関連するエラーが生じる可能性があります。
1exp = QgsExpression("1 + 1 = 2")
2if exp.hasParserError():
3 raise Exception(exp.parserErrorString())
4
5value = exp.evaluate()
6if exp.hasEvalError():
7 raise ValueError(exp.evalErrorString())