13

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.

3 Answers 3

29

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
    Commented Aug 29, 2014 at 14:44
  • isn't it layer.dataProvider().deleteFeatures(ids)? Commented 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. Commented Aug 13, 2015 at 21:34
  • 3
    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
    Commented Mar 9, 2016 at 2:29
12

There is also a possibility of using the deleteSelectedFeatures() method from the QgsVectorLayer class for deleting selected features:

# imports
from qgis.utils import iface

# choose an active layer
layer = iface.activeLayer()

# make your own selection
field_name = "DN" # specify your field
field_values = (1,2,3) # specify values for features that you want to retain
expression = f'"{field_name}" in {field_values}'
layer.selectByExpression(expression)

# delete selected features
if layer.selectedFeatureCount() > 0:
    layer.startEditing()
    layer.deleteSelectedFeatures()
    layer.commitChanges()
-1

If run from a script, exiting qgis will solve the issue, that is, including this part in the script:

qgs = QgsApplication([], False)
...
qgs.exitQgis()
os.remove()

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.