I have a PyQGIS script being run from within QGIS that updates attribute values in a GeoPackage, based on a mapping. It currently iterates through fields and features one by one, updating the values using QgsVectorLayer.changeAttributeValue
.
This seems inefficient, particularly if there are many features. I'm looking to update it to use QgsVectorDataProvider.changeAttributeValues
: https://qgis.github.io/pyqgis/3.28/core/QgsVectorDataProvider.html#qgis.core.QgsVectorDataProvider.changeAttributeValues
The changeAttributeValues
method takes as a parameter "attr_map (object) – a map containing changed attributes". Unfortunately, the documentation doesn't set out the format of the map, and a Google search hasn't yielded any useful information.
The aim is to update the code to create the attribute map, and then run one operation using changeAttributeValues
to update all changes at once. I am specifically looking for the format of the attribute map, though code is of course welcome.
The dummy existing code is as follows:
outfile = "c:/temp/output.gpkg"
oldFieldNames = ["oldField1", "oldField2", "oldField3"]
newFieldNames = ["newField1", "newField2", "newField3"]
mapping = [
{0: "orange", 1: "apple", 2: "pineapple"},
{0: "red", 1: "yellow", 2: "green", 3: "blue"},
{0: "dog", 1: "cat", 2: "goat", 3: "cow", 4: "fish"},
]
vl = QgsVectorLayer(outfile, 'temp', 'ogr')
pr = vl.dataProvider()
for i in range(len(oldFieldNames)):
newFieldIndex = pr.fieldNameIndex(newFieldNames[i])
with edit(vl):
for feature in vl.getFeatures():
vl.changeAttributeValue(feature.id(), newFieldIndex, mapping[i][feature[oldFieldNames[i]]])
If the initial layer attributes are as follows:
fid | oldField1 | oldField2 | oldField3 | newField1 | newField2 | newField3 |
---|---|---|---|---|---|---|
1 | 0 | 3 | 4 | |||
2 | 1 | 2 | 3 |
then the final result after mapping should be:
fid | oldField1 | oldField2 | oldField3 | newField1 | newField2 | newField3 |
---|---|---|---|---|---|---|
1 | 0 | 3 | 4 | orange | blue | fish |
2 | 1 | 2 | 3 | apple | green | cow |
As an aside, I have found quite regularly with the QGIS Python API documentation, that there is not enough detail to know the exact format of parameters required for some methods.
feature_id: {field_index:new value}, ... }
.