ArcGIS Pro – Using Multiple Label Colors for Better Visualization

arcgis-procolorlabeling

I would like to label a polygon feature class by 1 attribute class; however I would like the colour of the text of the label to change dependent on the value of the attribute class

I know that in ArcMap there was a way this could be done by writing out a VB script formula, to define a colour to a certain value, but in this specific case I have at least 60 different values, and every one needs its own colour

I know it could be done by hand with the Label Classes, but it feels like there has to be a better way?

Best Answer

Yes, this can be done - changing the colour of labels can be achieved like so:

import random

def FindLabel([ATTRIBUTE_TO_USE]):
    r = random.randint(0, 255)
    g = random.randint(0, 255)
    b = random.randint(0, 255)

    expression = f"<CLR red='{r}' green='{g}' blue='{b}'>" + [ATTRIBUTE_TO_USE]  + "</CLR>"
    return expression

The above scripts just generates random colours for each label and will reset every time. However, these random values could be saved to a new attribute in the attribute table called "RGB" or something similar. To do this:

import arcpy, random
aprx = arcpy.mp.ArcGISProject("CURRENT")
map = aprx.listMaps()[0]
layer = map.listLayers("Name of your layer")
fields = [f.name for f in arcpy.Describe(layer).fields]
value _values = {}

# save each unique value with its own colour
with arcpy.da.SearchCursor(layer, fields) as cursor:
    for row in cursor:
        value = row[fields.index("ATTR_NAME")]
        if attr not in value _values:
            r = random.randint(0, 255)
            g = random.randint(0, 255)
            b = random.randint(0, 255)
            random_rgb = (r, g, b)
            attr_values[value] = random_rgb

# for each row, match the attribute value to the colour
# save it as the value for the RGB attribute
with arcpy.da.UpdateCursor(layer, fields):
    for row in cursor:
        value = row[fields.index("ATTR_NAME")]
        random_rgb = attrToColour[value]
        row[fields.index("RGB")] = random_rgb
        cursor.updateRow(row)

These values can then be accessed in labelling so that they don't regenerate every time.

def FindLabel([RBG]):
    r = RBG[0]
    g = RBG[1]
    b = RBG[2]

    expression = f"<CLR red='{r}' green='{g}' blue='{b}'>" + [ATTRIBUTE_TO_USE]  + "</CLR>"
    return expression

Source