[GIS] Deleting only specific attributes (columns) by name in an attribute table in QGIS with Python

attribute-tablefields-attributespyqgisselect-by-attribute

I am attempting to delete select columns for the final output of the attribute table that I'm creating.I'm having trouble with deleting the attributes (columns) that I want, regardless of their index position. The major issue is that the code is hard coded based on the field index.

  • I have looked at many answers on this site and other sources. I could not find one that answers this specific question. If there is such an answer please link it and I can remove this question.

  • I'm looking for the versatility in deleting all the attributes except for the ones that I want to show in the attribute table without relying on hard coded indices. I have attempted a variety of conditional statements but could not get it to work.

CODE

# Use a list to collect the index of the fields.
fields = []

# Get the index of each field and add it to list.
for field in huff_model.fields():
    idx = huff_model.fieldNameIndex(field.name())
    fields.append(idx)

# Remove the index of the field from the list for the field that you don't 
# want deleted.
fields.remove(0)
fields.remove(14)
fields.remove(15)

# Delete the fields in the attribute table through their corresponding index 
# in the list.
huff_model.deleteAttributes(fields)

With the current code if you don't already know the position of fields you don't want deleted, than this code doesn't work. Furthermore, if a future layer has a similar attribute table but with even one less or one more field (this assumption is valid given the work I'd doing), hard coding would completely mess up the results as the index of the fields that shouldn't be deleted wouldn't be the same as what is currently coded. Each time the number of fields change, the code would have to be updated which seems completely unnecessary (see above).

My assumption would be to only add the field index to the list if not named field x or field y or field z. However, I cannot get it to work outside of hardcoding the index through fields.remove("insert index of field you don't want deleted") to remove the index of the field from the list of indices that will be used to delete the corresponding fields from the attribute table.

The first image below is my attribute table with the field indices indicated by the arrows which are used in field.remove(). There are 16 fields in total, and I don't want to delete the first, fifteenth and sixteenth fields (0, 14, 15 corresponding indices) from the attribute table.

Table before code is run

enter image description here

The second image below is the same attribute table, but with all the fields deleted except for the first, fifteenth and sixteenth fields from the first image (0, 14, 15 corresponding indices).

Table after code is run

enter image description here

Best Answer

This?

field_ids = []
# Fieldnames to keep
fieldnames = set(['CTUID','Primary','Secondary'])
for field in huff_model.fields():
    if field.name() not in fieldnames:
      field_ids.append(huff_model.fieldNameIndex(field.name()))

# Delete the fields in the attribute table through their corresponding index 
# in the list.
huff_model.dataProvider().deleteAttributes(field_ids)
huff_model.updateFields()
Related Question