[GIS] Scripting the mapping of style columns attributes in QGIS

categorized-rendererpyqgisqgisstyle

In a vector layer is it possible to tune up/scripting the style columns attributes to map "Label" column to a specific attribute field/column instead of being populated with same content as the "Value" column? I'm working on QGIS 2.14.

We have symbology by categories and symbols in a XML created based on a key field ("ID_UCF" [type integer]) which is used to classify the style attributes – match to symbols from file – but this way we have the legend of the map taking the "ID_UCF" codes as symbol labels and we need those labels as a description of those codes. This description/text is given by a column present in the attribute table of the label ("DSCR_UCF" [type text]).

How can we change the content of style column "Label" – in this case "Legend" to assume the descriptions?

We have been looking at qgis.core such as rendererV2 class but could not find how to deal with the issue.

enter image description here

Best Answer

Hoping I have understood well your issue, you may set the text from a specified field as Legend by directly creating the categorized style.

Assuming to start from this self-explanatory Attribute Table:

enter image description here

you may assign the "DSCR_UCF" field as Legend for the "ID_UCF" values using the following code from the Python Console:

from PyQt4.QtGui import *
import random

layer = iface.activeLayer()

my_dict = {}
for feat in layer.getFeatures(): #iterate over the features for defining the lookup: value -> (color, label) 
    if feat["ID_UCF"] not in my_dict.keys():
        color = QColor.fromRgb(random.randint(0,255),random.randint(0,255),random.randint(0,255)) #assign a random color
        my_dict[feat["ID_UCF"]] = (color.name(), feat["DSCR_UCF"]) #lookup: value -> (color, label) 
    else: # go to the next feature since the label is already stored
        continue

# Create a category for each item in my_dict
categories = []
for value, (color_name, label) in my_dict.items():
    symbol = QgsSymbolV2.defaultSymbol(layer.geometryType())
    symbol.setColor(QColor(color_name))
    category = QgsRendererCategoryV2(value, symbol, label)
    categories.append(category)

# Create the render and assign it to the layer
renderer = QgsCategorizedSymbolRendererV2("ID_UCF", categories)
layer.setRendererV2(renderer)
layer.triggerRepaint()

You will get this result:

enter image description here

EDIT

If you want to keep the original colors unchanged, you may run the following code (assuming you previously assigned a custom categorized renderer with custom colors):

from PyQt4.QtGui import *

layer = iface.activeLayer()
f_index = layer.dataProvider().fieldNameIndex('ID_UCF')
unique_values = layer.uniqueValues(f_index)
rend = layer.rendererV2()
colors = [symb.color().name() for symb in rend.symbols()]  
diz = dict(zip(unique_values, colors))

my_dict = {}
for feat in layer.getFeatures(): #iterate over the features for defining the lookup: value -> (color, label) 
    if feat["ID_UCF"] not in my_dict.keys():
        val = [diz[feat["ID_UCF"]]]
        val.append(feat["DSCR_UCF"])
        my_dict[feat["ID_UCF"]] = tuple(val) #lookup: value -> (color, label) 
    else: # go to the next feature since the label is already stored
        continue

# Create a category for each item in my_dict
categories = []
for value, (color_name, label) in sorted(my_dict.items()):
    symbol = QgsSymbolV2.defaultSymbol(layer.geometryType())
    symbol.setColor(QColor(color_name))
    category = QgsRendererCategoryV2(value, symbol, label)
    categories.append(category)

# Create the render and assign it to the layer
renderer = QgsCategorizedSymbolRendererV2("ID_UCF", categories)
layer.setRendererV2(renderer)
layer.triggerRepaint()