2

I've gone through many posts here that describe some ways of selecting features by attribute, but there is really no definitive answers as to which way is the fastest way of selecting features from a QgsVectorLayer by attribute values. Here is the case in point, I have a python list of attribute values, such as ['obj1', 'obj2', 'obj3'], these are the values of object 'name', which is also an attribute in the QgsVectoryLayer, say, layer. I need to select these map features on the map as fast as I can as the layer usually has hundreds of thousands of features. Here is a few ways I tried:

method 1:

name_list = ['obj1', 'obj2', 'obj3']
feature_ids = [f.id() for f in layer.getFeatures() if f.attributes()[0] in name_list]
layer.setSelectedFeatures(feature_ids)

method 2:

feature_ids = []
for n in name_list:
   for feature in layer.getFeatures(QgsFeatureRequest(QgsExpression('"name"=' + "'" + n + "'"))):
      feature_ids.append(feature.id())
layer.setSelectedFeatures(feature_ids)

neither of the above is fast, when executed over a few large layers, it is really slow. So, what would be the fastest way to select features on map fast by attribute values.

To time it: one can put the above methods into functions, then do the following to time it:

import timeit
print "method1: %s seconds " % timeit.timeit(method1,number=1)
print "method2: %s seconds " % timeit.timeit(method2,number=1)

The QGis Core library is from QGIS 2.12.3 Lyon; GDAL/OGR 1.11.3; GEOS 3.5.0-CAPI-1.9.0

2
  • I think your timing code should be merged into your two code snippets and the results of running each presented.
    – PolyGeo
    Commented Jun 29, 2017 at 22:30
  • 1
    Did the answer help you solve the problem? Commented Jul 25, 2017 at 16:33

1 Answer 1

5

I suggest you to follow recommendations given in this answer to Optimizing QgsFeatureRequest with filter expression. If your data is on a database, create an index for the name field.

Finally, give this code snippet a try, it has additional optimizations for your case:

expr = "\"name\" IN ('{}')".format( "','".join( name_list ) )
req = QgsFeatureRequest().setFlags( QgsFeatureRequest.NoGeometry )
req.setSubsetOfAttributes( [] ).setFilterExpression( expr ) 

it = layer.getFeatures( req )
layer.setSelectedFeatures( [f.id() for f in it] )

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.