10

How to remove or delete column fields in a shapefile using PyQGIS?

0

3 Answers 3

14

If you get no joy with QGSVectorLayer::deleteAttribute as they docs say: delete an attribute field (but does not commit it) have a look at the data provider. As QGIS deals with lots of feature types with different drivers I suspect that it's left up to the driver as to whether or not a field can be deleted.

Here's some code that I dredged up that may help:

fields = vlayer.dataProvider().fields()

count = 0
for name, field in fields.iteritems():
    if field.name() == fieldName:
        return count
    count += 1

To get the index of the field from the name. In this case I'm not using .upper() but I would recommend it.

After getting the index of the field you (might) delete it using the dataprovider.

fList = list()
fList.append(count)
vlayer.dataProvider().deleteAttributes(fList)

It's expecting a list so the integer needs to be put into a list. I have not used this method; normally I would use ArcMap to delete the field.

As pointed out by RogerHuang, the fields of the layer may need to be updated now that they have been changed to refresh the layers' fields definition:

vlayer.updateFields()
5
  • 4
    vLayer.fieldNameIndex('YourFieldName') might be a easier way to get index
    – vinayan
    Commented Aug 1, 2014 at 5:05
  • Thanks @vinayan, I have overlooked that one. The code I took this from is quite old, that function may be newer than my code. Commented Aug 1, 2014 at 5:23
  • Thanks, It worked well Is there way to get max. index number ? I have an error "return outside function" Thanks for answers
    – Nahm
    Commented Aug 1, 2014 at 23:47
  • Thanks for answers all of my problems solved and I combined ideas to find max. field index by following ways count = layer.dataProvider().attributeIndexes() print count maxindex = count[-1] print maxindex
    – Nahm
    Commented Aug 2, 2014 at 0:34
  • 1
    layer.updateFields() seems to be needed, in order to regenerate fields from data provider. qgis.org/api/classQgsVectorLayer.html Commented Oct 6, 2017 at 6:57
14

For PyQGIS 3 this might be the easiest way to delete a single field:

# Get a layer object and enter edit mode:
my_vectorlayer = iface.activeLayer()
with edit(my_vectorlayer):
    # Get the field index by its name:
    my_field = my_vectorlayer.fields().indexFromName('name of field you want to delete')
    # Delete the field by its index, note that it has to be in a list:
    my_vectorlayer.dataProvider().deleteAttributes([my_field])
# Update the fields, so the changes are recognized:
my_vectorlayer.updateFields()

Or if you want to delete multiple fields at once, you can go for this slightly modified:

# Get a layer object:
my_vectorlayer = iface.activeLayer()
# Create a list of the fieldnames you want to delete:
fieldnames_to_delete = ['field_a','field_c']
# Enter Edit mode
with edit(my_vectorlayer):
    # Create empty list we will fill with the fieldindexes
    fields_to_delete = []
    # Iterate over the list of fieldnames and get the indexes
    for fieldname_to_delete in fieldnames_to_delete:
        # Get the field index by its name:
        fieldindex_to_delete = my_vectorlayer.fields().indexFromName(fieldname_to_delete)
        # You can also check if the field exists
        if fieldindex_to_delete == -1:
            # If it does not exist, just skip it and go to the next one. This may prevent a crash or error :)
            continue
        # Append the index to the list
        fields_to_delete.append(fieldindex_to_delete)
    # Delete the fields by their indexes, note that it has to be a list:
    my_vectorlayer.dataProvider().deleteAttributes(fields_to_delete)
# Update the fields, so the changes are recognized:
my_vectorlayer.updateFields()
2
  • what do i need to do if i want to delete multiple fields by name? Commented Sep 12, 2022 at 15:17
  • thank you very much!! Commented Sep 12, 2022 at 15:30
10

There's several methods but I will mention the ones I normally use, both using the Python Console.


For SINGLE shapefiles:

  • Method 1 - Using a method utilising the QGIS algorithm - Delete Column:

    output_0=processing.runalg('qgis:deletecolumn', myshapefile.shp, "myFirstField", None)
    output_1=processing.runalg('qgis:deletecolumn', output_0['OUTPUT'], "mySecondField", None)
    output_2=processing.runalg('qgis:deletecolumn', output_1['OUTOUT'], "myThirdField", myoutput.shp)
    
  • Method 2 - Deleting the fields directly by selecting the layer from the Layers window (Table of Contents) and using the following code:

    layer = qgis.utils.iface.activeLayer()              # Sets the selected layer as the active layer
    res = layer.dataProvider().deleteAttributes([0])    # The [0] represents the 1st field, so [1] is the 2nd field etc. To delete multiple fields, use the comma to separate. Eg. [0, 2, 4]
    layer.updateFields()                                # Updates the layer with the changes
    

For MULTIPLE shapefiles:

  • Following on from Method 1, you can use the following script which was tested with 2 folders on the Desktop - "Testing" (which contained the shapefiles) and "Results" (which will contain the output shapefiles of the script):

    import processing, os, glob
    
    from os.path import expanduser
    home = expanduser("~")
    
    result_path = home + "\Desktop\Results\\"
    os.chdir(home + "\Desktop\Testing\\")
    
    for fname in glob.glob("*.shp"):
        output_0=processing.runalg('qgis:deletecolumn', fname, "myFirstField", None)
        output_1=processing.runalg('qgis:deletecolumn', output_0['OUTPUT'], "mySecondField", None)
        output_2=processing.runalg('qgis:deletecolumn', output_1['OUTPUT'], "myThirdField", result_path + fname)
    
    print "All done!"
    
  • Following on from Method 2, you can use the following code if you have multiple shapefiles loaded in your Layers window without having to select them individually.

    for layer in QgsMapLayerRegistry.instance().mapLayers().values():
        res = layer.dataProvider().deleteAttributes([0])
        layer.updateFields()
    

Hope this helps!

1
  • I've done as you suggested in the 1st method but appeared this comment: "Error: Wrong parameter value: None". I can´t use the 2nd method because I have to do the same for a large number of shapefiles, about 8000. Any idea? Commented Jun 30, 2015 at 13:16

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.