4

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?

Taras
35.7k5 gold badges77 silver badges151 bronze badges
asked Jun 9, 2023 at 8:15
2
  • I'm confused: Why was my code 'edited' without being changed in any way? Commented Jun 10, 2023 at 22:35
  • Editing is a normal part of these sites. In the above case, the tag pyqgis was added to the backticks to tell it how to colourize it. Commented Jun 14, 2023 at 13:26

2 Answers 2

7

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)

enter image description here

answered Jun 9, 2023 at 8:46
3
  • 1
    Oh, this looks very nice, kind of elegant! Thank you very much, I will try it! Commented 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? Commented Jun 11, 2023 at 17:32
  • Oh. Try replacing f2 or f1 or -999 with next(item for item in [f2, f1, -999] if item is not None) Commented Jun 12, 2023 at 6:49
1

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:

result

P.S. To achieve -999 where "field1" and "field2" are both NULLs, please modify the expression accordingly:

expression = QgsExpression('coalesce("field1", "field2", -999)')

References:

answered Jun 10, 2023 at 10:11

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.