TransWikia.com

PyQGIS - Filter features with id

Geographic Information Systems Asked on March 2, 2021

I wan’t to filter features of a Shapefile layer from a user’s selection with PyQGIS. When I select less than 30 features with a method like fid=1 or fid=2 or fid=3 ..., everything works fine but when I select over 30 features filter doesn’t work and return me all the features of the layer. If I try a filter like fid >= 1 and fid <=150 (for example), it works. But it doesn’t help for lists of unfollowing ids. I’m using QGIS 3.10.2.

Is there something wrong with this ? Does filters have size limits ? Is there a better way to filter features ?

# Layer
layer = iface.activeLayer()
features = layer.selectedFeatures()

# List ID of selected features
l = []
for feature in features:
    l.append(feature.id())
    
# Build arguments for the query
index = 0
query = []
prefix = 'fid='
while index < len(l)-1:
    query.append(prefix)
    query.append(l[index])
    query.append(' or ')
    index+=1
                
# Last element of the list
query.append(prefix)
query.append(l[index])
    
# Query
fullQuery = str(query).strip('[]').replace(',', '').replace("'", "")
    
# Filter
layer.setSubsetString(fullQuery)

2 Answers

I don't know if this solves your question, but in general, instead of

fid = 1 or fid = 2 or...

you should use

fid in (1,2,...)

It improves code readability.

Correct answer by Germán Carrillo on March 2, 2021

I am not sure what is wrong in your code but I have prepared a simple example that applies a filter based on features' id following the same logic of your example and it works fine with large number of features (e.g., 88 in this example). I am using QGIS 3.10.11:

# 1) Load a vector layer from natural earth database and import it to the project
gpkg_address = r"c:%DATA_PAATH%natural_earth_vector_50m_10m.gpkg"
lyr_name = "natural_earth_vector_50m_10m ne_10m_admin_0_countries"
lyr = QgsVectorLayer("{}|{}".format(gpkg_address, lyr_name), lyr_name, "ogr")
QgsProject.instance().addMapLayer(lyr)

# 2) Count the number of overall features, and select only the features with population over 10 millions
n_feat_tot = lyr.featureCount()
s_pop = "POP_EST"
lyr.selectByExpression('"{}" > {}'.format(s_pop, 10e6))
n_feat_sel = lyr.selectedFeatureCount()
print("Total features: {}, selected features: {}".format(n_feat_tot, n_feat_sel))
# Total features: 255, selected features: 88

# 3) Get the id of selected features. Remove the selection and then prepare the query. Finally, apply the query to the layer and count the remaining features. 
feat_id = lyr.selectedFeatureIds()
lyr.removeSelection()
query = [" or ".join(["fid={}".format(el) for el in feat_id])]
lyr.setSubsetString(query[0])
n_feat_subset = lyr.featureCount()
print("Subset features: {}".format(n_feat_subset))
# Subset features: 88

The input data are from Natural Earth database. I hope this helps.

Answered by fastest on March 2, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP