12

I have a shapefile with only one field "DN". I would like to delete all features which does not have specific value of the field. Let's say the "DN" can be 1,2 or 3.

So far I was able to find out how to select Features and how to delete feature, but I did not succeed to combine them. Let's say I want only features with "DN" = 3 to remain:

Selection of the Features found here : Filter features based on their attributes using Python, however, I do not know if it does what it is supposed to do since I did not find the way how to check what is inside.

select = layer.getFeatures(QgsFeatureRequest().setFilterExpression(u'"DN"!=3'))

delete features found in the PyQGIS Developer Cookbook

res = Ilayer.dataProvider().deleteFeatures()

As far as I know, the deleteFeatures() requires "ID"s of the features, but I have no idea how to get them from from select which is QgsFeatureIterator.

2 Answers 2

23

You can loop over the iterator and get the id() for every feature in it:

with edit(layer):
    # build a request to filter the features based on an attribute
    request = QgsFeatureRequest().setFilterExpression('"DN" != 3')

    # we don't need attributes or geometry, skip them to minimize overhead.
    # these lines are not strictly required but improve performance
    request.setSubsetOfAttributes([])
    request.setFlags(QgsFeatureRequest.NoGeometry)

    # loop over the features and delete
    for f in layer.getFeatures(request):
        layer.deleteFeature(f.id())

or with QGIS < 2.12

request = QgsFeatureRequest().setFilterExpression('"DN" != 3')
request.setSubsetOfAttributes([])
request.setFlags(QgsFeatureRequest.NoGeometry)

ids = [f.id() for f in layer.getFeatures(request)]

layer.startEditing()
for fid in ids:
    layer.deleteFeature(fid)
layer.commitChanges()
4
  • Thank you, that was that! I just noticed that the FilterExpression was wrong (not u'"DN"=2||"DN"=1' but u'"DN"!=3' should be used). Please if you would edit your answer for this not to confuse other viewers.
    – MasterPJ
    Aug 29, 2014 at 14:44
  • isn't it layer.dataProvider().deleteFeatures(ids)? Aug 13, 2015 at 12:34
  • Using dataProvider() is possible but I prefer to work directly on the layer since this way the changes are communicated internally (to the map canvas, attribute table...) and other reasons. Aug 13, 2015 at 21:34
  • 2
    layer.dataProvider().deleteFeatures(ids) has thrown crashes for me when layer.deleteFeature(fid) didnt... Bad crashes. The kind that cause a seg fault and kill qgis. The kind that take 6 hours to find... stick with the answer posted here. Bums me out because layer.dataProvider().deleteFeatures(ids) is all through my code and now I've got to fix it all.
    – Mr Purple
    Mar 9, 2016 at 2:29
5

One can also use the following code:

layer = iface.activeLayer()

field_name = "DN" # specify your field
field_values = (1,2,3) # specify values for features that you want to retain

expression = f'"{field_name}" not in {field_values}'

layer.selectByExpression(expression)

layer.startEditing()
layer.deleteSelectedFeatures()
layer.commitChanges()

It contains a special method for deleting selected features deleteSelectedFeatures().

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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