PyQGIS – Change Feature IDs of a Layer Efficiently

feature-idpyqgis

How can I change the feature id's of a layer using PyQGIS to an attribute value of that feature, where the attribute value is a unique integer? Is that possible at all, and if so, how?

Things like:

for feat in layer.getFeatures():
    print(feat.id())
    feat.id() = feat['myattr']
    layer.updateFeature(feat)
    print(feat.id())

seem not to be the way to do this. The layer is of type memory, so not physically stored on a harddrive.


Some background on why I want to do insane stuff like that:

Using PyQGIS I have a point-inputlayer having a feature id and this same feature id also as attribute value fid. Now I am running the processing algorithm Voronoi Polygons on it. Issue is, that these voronoi polygons will have a different feature id than the original corresponding input, but the same attribute fid. So on the voronoilayer, the attribute fid and the feature id are different, while they are the same on the pointlayer. Since I work a lot with spatial indizes in this script, which return the feature id instead of the feature itself I can no longer use voronoilayer.getFeature(pointfeatureid_from_spatialindex) to "re-"get the feature itself, but always need to use some more complicated stuff like:

pointfeat = pointlayer.getFeature(pointid_from_index)
myattr = pointfeat.id()
expression = QgsExpression( " \"{fieldname}\" = '{value}' ".format(fieldname='fid',value=myattr) )
request = QgsFeatureRequest(expression)
voronoifeat = voronoilayer.getFeatures(request)
voronoifeat = list(voronoifeat)[0]

Which makes things a little more complicated. So if possible I'd like to skip this and be able to use voronoifeat = voronoilayer.getFeature(pointid_from_index) directly.

Is it possible to change the feature id's of an existing layer or would I need to create a new layer and add the copied features from the old layer in my wanted order one after another?

While I (for now) accepted a good workaround on my actual issue, I am still interested in the actual answer to the question.

Best Answer

Not sure why you don't do a double mapping that enable you to match id from point layer to voronoi layer, like below? It's a purely Python approach that should be enough. It should do the equivalent of your wanted voronoifeat = voronoilayer.getFeature(pointid_from_index) ?

mapping_id_voronoi = {f['fid']: f.id() for f in voronoilayer.getFeatures()}
mapping_id_point = {f.id(): f['fid'] for f in pointlayer.getFeatures()}

voronoilayer.getFeature(mapping_id_voronoi[mapping_id_point[pointid_from_index]])
Related Question