2

I currently have a vector layer that contains intensity polygons and are colour co-ordinated depending on the level of intensity. Within this 'Intensity' file, there are two columns Intensity and Affected_P. The file currents shows the intensity in the legend for the symbology but I would like to include the sum statistic created - Affected_P too the legend as well. So, for example, the legend with the intensity then the Affected_P field in brackets - 2.4 (60,000). Ideally, done within the Python Console.

The fields/columns look like this. Currently, there are multiple Affected_P values for one intensity. I am not too sure if it would add all the values automatically when adding to the specific intensity legend you want or that you would have to add in a piece of code to this.

enter image description here

The legend looks like this currently but I would like the Affected_P column shown next to the intensity number for each colour enter image description here

Invalid syntax error when I try to add the code to python, under where I have changed the symbology.

#Change symbology
default_style = QgsStyle().defaultStyle()
color_ramp = default_style.colorRamp('Spectral') #Spectral color ramp
color_ramp.invert()

layer = QgsProject().instance().mapLayersByName('Intensity')[0]
field_index = layer.fields().lookupField('Intensity')
unique_values = list(layer.uniqueValues(field_index))
categories = []
for value in sorted(unique_values):
    symbol = QgsSymbol.defaultSymbol(layer.geometryType())
    category = QgsRendererCategory(value, symbol, str(value))
    categories.append(category)
renderer = QgsCategorizedSymbolRenderer( "intensity" || ' - ' || sum("affected_p","intensity"), categories) 
renderer.updateColorRamp(color_ramp)

enter image description here

6
  • 1
    Are you asking about the legend-item in the print composer, or about the display in the layers tree? – Erik Feb 23 at 12:35
  • Display in the layers tree. If it is unavailable to do it within the layers tree, then the legend-item in the print composer is okay! Thanks – LiamHems Feb 23 at 12:35
  • 1
    Using QGIS 3.16 you may edit entries in the legend-item using expressions. I don't know, whether you may edit the entries in the layer tree. – Erik Feb 23 at 12:36
  • Ah okay I see thank you. I will see if anyone answers as to whether to edit the entries in the layer tree. Would you know how to use a code to edit the entry in the legend-item? Thanks – LiamHems Feb 23 at 12:38
  • Please place code in the Question body as text. This makes it legible, searchable, and reproducible without tedious copying. – Vince Feb 23 at 14:33
1

To adapt the code you are using to categorize based on the expression suggested by @JGH, you actually need to create the list of unique values and QgsRendererCategory list based on the expression.

Please try the code below, adapted (and 'Pythonicized') from the logic in the addCategories() method of QgsCategorizedSymbolRendererWidget class which starts at line 760 of qgscategorizedsymbolrendererwidget.cpp.

default_style = QgsStyle().defaultStyle()
color_ramp = default_style.colorRamp('Spectral') #Spectral color ramp
color_ramp.invert()

layer = QgsProject().instance().mapLayersByName('Intensity')[0]

exp_string = '"Intensity" || \' -\' || \' (\' || sum("Affected_P", "Intensity") || \')\''
unique_values = []
exp = QgsExpression(exp_string)
#print(exp.isValid())
context = QgsExpressionContext()
context.appendScope(QgsExpressionContextUtils.globalScope())
context.appendScope(QgsExpressionContextUtils.projectScope(QgsProject.instance()))
context.appendScope(QgsExpressionContextUtils.atlasScope(None))
context.appendScope(QgsExpressionContextUtils.layerScope(layer))
exp.prepare(context)
for feat in layer.getFeatures():
    context.setFeature(feat)
    val = exp.evaluate(context)
    if val not in unique_values:
        unique_values.append(val)
#print(unique_values)

categories = []
for value in sorted(unique_values):
    symbol = QgsSymbol.defaultSymbol(layer.geometryType())
    category = QgsRendererCategory(value, symbol, str(value))
    categories.append(category)
renderer = QgsCategorizedSymbolRenderer(exp_string, categories) 
renderer.updateColorRamp(color_ramp)
layer.setRenderer(renderer)
layer.setOpacity(0.55)
layer.triggerRepaint()
2
  • Thank you very much for your help. It works perfectly. – LiamHems Feb 24 at 9:59
  • No problem, glad to hear it worked. – Ben W Feb 24 at 10:28
4

Instead of categorizing the data by intensity, you can categorized it by a concatenation of intensity and affected_p

The expression would be similar to "intensity" || ' - ' || sum("affected_p","intensity")

The example below use the average instead of the sum: enter image description here

5
  • When I use the python console, I currently use this code but it says that the || are invalid syntax. I will add a screenshot above. – LiamHems Feb 23 at 14:26
  • 1
    make this expression (all of it, including the ', " and ||) a string in your python code – JGH Feb 23 at 15:11
  • I have used the expression: renderer = QgsCategorizedSymbolRenderer(str("intensity" || ' - ' || sum("affected_p","intensity")), categories) but it still comes up with 'Invalid Syntax'... – LiamHems Feb 23 at 15:20
  • 1
    no, you must create a string that contains ALL of the given information.. something like "\"intensity\" || ' - ' || sum(\"affected_p\",\"intensity\"" (note the surrounding double quotes and, inside the expression, the escaping of the double quotes that should be retained) – JGH Feb 23 at 15:48
  • Thank you for your help. When I run the script now it works but only when I go on to the Intensity file symbology and re-classify the data. Do you know why this is the case? Do I need to write a code like 'renderer.update...'? Thanks – LiamHems Feb 23 at 16:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.