I have two fields which I want to merge into a single field, thereby should one of the two to-be-merged fields be prioritized, meaning, if a value of one field is available take it instead of the other field.
I would like to have it like this:
field1 | field2 | resultField
-----------------------------
13 | NULL | 13
28 | 56 | 56
44 | NULL | 44
11 | 17 | 17
So the "field2"
should be prioritized in the resulting field.
I know, that I will need to create a new field, with the name relevant field name, so
vectorLyr = QgsVectorLayer('path_to_filed', 'layername', "ogr")
vectorLyr.isValid()
vpr = vectorLyr.dataProvider()
fieldnames = [resultField]
for name in fieldnames:
vpr.addAttributes([QgsField(name, QVariant.Double)])
vectorLyr.updateFields()
However, how can I now update the "resultfield"
with the values from the two fields?
2 Answers 2
You can use or
like this, i think it is called Ternary operators:
layer = iface.activeLayer()
p = layer.dataProvider()
field_to_update = "field3"
fieldindex = layer.fields().indexOf(field_to_update)
attributemap = {} #A dictionary to store {feature id: {index of field to update : new value}}
for f in layer.getFeatures(): #For each feature
f1, f2 = f["field1"], f["field2"] #Extract the values in field1 and field2
attributemap[f.id()] = {fieldindex: f2 or f1 or -999} #Take the first not null value, or if there is none, use -999
#attributemap[1]
#{4: 83} Feature 1 should in field 4 get the value 83
p.changeAttributeValues(attributemap)
-
1Oh, this looks very nice, kind of elegant! Thank you very much, I will try it!i.i.k.– i.i.k.2023年06月09日 09:25:03 +00:00Commented Jun 9, 2023 at 9:25
-
I adjusted my code accordingly and ran into a little problem: Python interpretes the value 0 as NULL, so that all values which are 0 or NULL become -999. However, 0 is 0 and not 'None'. Any idea how to tackle this problem?i.i.k.– i.i.k.2023年06月11日 17:32:55 +00:00Commented Jun 11, 2023 at 17:32
-
Oh. Try replacing
f2 or f1 or -999
withnext(item for item in [f2, f1, -999] if item is not None)
Bera– Bera2023年06月12日 06:49:42 +00:00Commented Jun 12, 2023 at 6:49
Another approach might be not as Pythonic as was suggested by @BERA, however, it is still applicable in terms of PyQGIS.
It utilizes the coalesce()
function inside the QgsExpression()
class.
Proceed with Plugins > Python Console > Show Editor
and paste the script below
from qgis.core import QgsProject, QgsExpression, QgsExpressionContext, QgsExpressionContextUtils
# refer to a layer by its name
layer = QgsProject.instance().mapLayersByName("lines")[0]
# set up an expression including two desired fields
expression = QgsExpression('coalesce("field1", "field2")')
# define the expression context to encapsulate parameters for evaluation
context = QgsExpressionContext()
context.appendScopes(QgsExpressionContextUtils.globalProjectLayerScopes(layer))
# start layer editing
with edit(layer):
for feat in layer.getFeatures():
context.setFeature(feat)
feat["result"] = expression.evaluate(context)
layer.updateFeature(feat)
Press Run script
run script and get the output that will look like:
P.S. To achieve -999 where "field1"
and "field2"
are both NULL
s, please modify the expression accordingly:
expression = QgsExpression('coalesce("field1", "field2", -999)')
References:
Explore related questions
See similar questions with these tags.
pyqgis
was added to the backticks to tell it how to colourize it.