[GIS] Batch add column to layers and add layer prefix in PyQGIS

batchpyqgispythonqgis

I have a number of layers each with a prefix like A_ B_ and so forth.

I'd like to:

  1. Add a column (text) called DENSITY to each shp
  2. Add the prefix letter from the layer name to each row in the DENSITY column for each shp file.

Can it be done?

I'm using QGIS 2.8.1


Update:

I think there was a typo here with a missing +

print "- layer: " child.layerName() + "  ID: " + child.layerId()

and I ran this:

# Iterate through the Legend to find all groups and layers
root = QgsProject.instance().layerTreeRoot()

for child in root.children(): 
    if isinstance(child, QgsLayerTreeGroup):
    print "- group: " + child.name()

# If we find a group, save the prefix name

    prefix = group.name().split('_')[0]
    elif isinstance(child, QgsLayerTreeLayer):
    print "- layer: " + child.layerName() + "  ID: " + child.layerId()
    layer = child.layer()

# Add code to add a field named density to the layer.
#######
# Add code to iterate through each feature in the layer and populate the field with prefix value
#######

but got these errors:

line 4, in
root = QgsProject.instance().layerTreeRoot()
AttributeError: 'QgsProject' object has no attribute 'layerTreeRoot'

Image if split files:

Best Answer

You can achieve it by running the following code snippet in the QGIS Python console:

from PyQt4.QtCore import QVariant
for layer in QgsMapLayerRegistry.instance().mapLayers().values():
    prefix = layer.name().split("_")[0]
    res = layer.dataProvider().addAttributes([QgsField("density", QVariant.String)])
    layer.updateFields()
    fieldIndex = layer.dataProvider().fieldNameIndex( "density" )
    attrFeatMap = {}
    attrMap = { fieldIndex : prefix }
    for feature in layer.getFeatures():
        attrFeatMap[ feature.id() ] = attrMap
    layer.dataProvider().changeAttributeValues( attrFeatMap )

I assume the only layers you have loaded in the QGIS ToC are those you want to modify. Otherwise, you would need to validate things like the layer type (i.e., you don't want the script to run on raster layers).

The script iterates through layers loaded into QGIS, extracts the prefix from their names, creates the text field density, builds a dictionary like this:

{ featureId : { fieldIndex : value } }

for each feature, and finally, applies the dictionary to change features' density values.

enter image description here

Let me know if something is not clear.