Geographic Information Systems Asked on January 14, 2021
Is there a way to add features from one layer to another while matching attribute names using Python?
Using QGIS 3.10.8
I am trying to add features to an existing layer. I have been using the code below to add the features, this code however does not match the attribute names and populates the added features in the order of the layer I am obtaining features from.
For example: If I have N-1 attributes in the layer I am obtaining the features from, the data will add features, but will add "NULL" to the last attribute columns, while the attributes with "NULL" should have been somewhere else, illustrated in the picture at the bottom.
Is there a way to ensure that features get added to the correct attribute?
layer = QgsVectorLayer(Out, "Out","ogr")
feats = []
for feat in Inn.getFeatures():
feats.append(feat)
layer.startEditing()
dp = layer.dataProvider()
dp.addFeatures(feats)
layer.commitChanges()
I wrote this script a while ago which should do what you want. The key is setting up your field mapping in nested lists. You can use this approach to match fields with completely different names and have control over matching which attributes are copied to which field in the target layer. However, in your case, it will ensure that 'Att2' will be copied to 'Att2', 'Att3' to 'Att3' etc. If you have an 'Att1' field in your target layer, it will be either empty or Null for the copied feature. You will need to change the layer names in the script to match your source and target layer names.
project = QgsProject().instance()
# Set up field mapping in lists below e.g. ['Layer A field name', 'Layer B field name']
fld_map = [['Att2', 'Att2'],
['Att3', 'Att3']]
layer_1 = project.mapLayersByName('Layer_A')[0] # change 'Layer A' to the name of your source layer
L1_feats = [f for f in layer_1.getFeatures()]
layer_2 = project.mapLayersByName('Layer_B')[0] # change 'Layer B' to the name of your target layer
pr_2 = layer_2.dataProvider()
layer_2.startEditing()
for feat in L1_feats:
atts = {}
for item in fld_map:
atts[layer_2.fields().lookupField(item[1])]= feat.attribute(layer_1.fields().lookupField(item[0]))
L2_feat = QgsFeature()
L2_feat.setGeometry(feat.geometry())
pr_2.addFeature(L2_feat)
pr_2.changeAttributeValues({L2_feat.id(): atts})
layer_2.commitChanges()
layer_2.updateExtents()
I actually started implementing this in a plugin but got sidetracked and never finished it off. I'm still intending to finish it when I get a chance and upload it to the repository.
Correct answer by Ben W on January 14, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP