Loop Through Multiple classificationFields

593
1
Jump to solution
10-08-2021 08:22 AM
JaredPilbeam2
MVP Regular Contributor

In my Pro project, I have 8 maps with 3 layers each. I'm writing a script that iterates the layers in each map, and changes the break values of these layers. There is one more step where I'd be grateful for some direction. And that is with setting multiple classificationFields.

I know how to set the break values using one classificationField, anyway. I'm not sure I'm doing this right, but in order to give each layer its particular classificationField which corresponds to that particular map I've created a list.

 

#create fields list. for every map, change the symbology based on its corresponding field
sym.renderer.fields = ['VaccPercentageTotPop', 'VaccPercentage0to18', 'VaccPercentage11to14', 
'VaccPercentage12to18', 'VaccPercentage14to16', 
'VaccPercentage16to18', 'VaccPercentage19to64', 'VaccPercentage65Plus']

 

 

I'm using sym.renderer.fields because it seems to allow a list, which I'm referencing from this SE post. In the Pro docs I don't see any help with multiple fields. This will throw an error with a list:

sym.renderer.classificationField = ...

 

The following script iterates the layers and the maps successfully, but nothing happens to the layers.

 

 

import arcpy
aprx = arcpy.mp.ArcGISProject(r'\\path to\TestDelete.aprx')

def values():
    for map in aprx.listMaps():
        print(f'map: {map.name}')
        layers = map.listLayers()
        for layer in layers:
            sym = layer.symbology
                    
            if hasattr(sym, 'renderer') and layer.name.startswith('BaseLayer'):
                    sym.updateRenderer('GraduatedColorsRenderer')
                    print(f'Updated Graduated colors renderer: {layer}')

                    Renderer = sym.renderer
                    classbreakvalues = [40, 45, 56.8, 100]
                    classbreaklabels = ['0-40%', '41-45%', '46-56.8%', '56.9-100%']
                    Renderer.breakCount = len(classbreakvalues)
                    print(f'Set the break count value: {layer}')
                    #Renderer.classificationMethod = 'Manual Interval'
                    
                    #create fields list. for every map, change the symbology based on its corresponding field
                    sym.renderer.fields = ['VaccPercentageTotPop', 'VaccPercentage0to18', 'VaccPercentage11to14', 'VaccPercentage12to18', 
                    'VaccPercentage14to16', 'VaccPercentage16to18', 'VaccPercentage19to64', 'VaccPercentage65Plus']

                    i = 0 
                    for brk in Renderer.classBreaks:
                        brk.upperBound = classbreakvalues[i]
                        brk.label = classbreaklabels[i]
                        i+=1

                    layer.symbology = sym
                    aprx.save()
values()

 

 

0 Kudos
1 Solution

Accepted Solutions
JaredPilbeam2
MVP Regular Contributor

A bunch of changes later I was able to get what I wanted, which is a script that changes the break values of multiple layers in multiple maps using multiple fields. I needed a counter, which until now I only copied but wasn't sure how to use. Also, don't know if this is a bug or not, but you can't give the condition for a GraduatedColorsRenderer if it is already. You have to "reset" the renderer. I was able to do this by changing the renderer to SimpleRenderer then back to GraduatedColorsRenderer. And by not setting a renderer at all I didn't get any results. Also, by remove the save() line it ran much faster.

Here's a working script:

import arcpy
aprx = arcpy.mp.ArcGISProject('CURRENT')

#make sure fields in list are in same order as maps in project
fields =  ['VaccPercentageTotPop', 'VaccPercentage11to14', 'VaccPercentage0to18', 'VaccPercentage12to18',  
           'VaccPercentage14to16', 'VaccPercentage16to18', 'VaccPercentage19to64', 'VaccPercentage65Plus']

c = 0 # use counter to give a number to each map in for loop
for map in aprx.listMaps():
    print(f'--- map: {map.name} ---')
    layers = map.listLayers()
    for layer in layers:
        print(f'layer: {layer.name}')
        sym = layer.symbology 
        #reset renderer
        sym.updateRenderer('SimpleRenderer')
        sym.updateRenderer('GraduatedColorsRenderer')

        if hasattr(sym, 'renderer') and layer.name.startswith('BaseLayer'):
            Renderer = sym.renderer
            Renderer.classificationField = fields[c]

            classbreakvalues = [40, 45, 60, 100]
            classbreaklabels = ['0-40%', '41-45%', '46-60%', '60.4%-100%']
            Renderer.breakCount = len(classbreakvalues)

            i = 0 
            for brk in Renderer.classBreaks:
                brk.upperBound = classbreakvalues[i]
                brk.label = classbreaklabels[i]
                i+=1

                layer.symbology = sym

#                     aprx.save()
    c+=1

 

View solution in original post

0 Kudos
1 Reply
JaredPilbeam2
MVP Regular Contributor

A bunch of changes later I was able to get what I wanted, which is a script that changes the break values of multiple layers in multiple maps using multiple fields. I needed a counter, which until now I only copied but wasn't sure how to use. Also, don't know if this is a bug or not, but you can't give the condition for a GraduatedColorsRenderer if it is already. You have to "reset" the renderer. I was able to do this by changing the renderer to SimpleRenderer then back to GraduatedColorsRenderer. And by not setting a renderer at all I didn't get any results. Also, by remove the save() line it ran much faster.

Here's a working script:

import arcpy
aprx = arcpy.mp.ArcGISProject('CURRENT')

#make sure fields in list are in same order as maps in project
fields =  ['VaccPercentageTotPop', 'VaccPercentage11to14', 'VaccPercentage0to18', 'VaccPercentage12to18',  
           'VaccPercentage14to16', 'VaccPercentage16to18', 'VaccPercentage19to64', 'VaccPercentage65Plus']

c = 0 # use counter to give a number to each map in for loop
for map in aprx.listMaps():
    print(f'--- map: {map.name} ---')
    layers = map.listLayers()
    for layer in layers:
        print(f'layer: {layer.name}')
        sym = layer.symbology 
        #reset renderer
        sym.updateRenderer('SimpleRenderer')
        sym.updateRenderer('GraduatedColorsRenderer')

        if hasattr(sym, 'renderer') and layer.name.startswith('BaseLayer'):
            Renderer = sym.renderer
            Renderer.classificationField = fields[c]

            classbreakvalues = [40, 45, 60, 100]
            classbreaklabels = ['0-40%', '41-45%', '46-60%', '60.4%-100%']
            Renderer.breakCount = len(classbreakvalues)

            i = 0 
            for brk in Renderer.classBreaks:
                brk.upperBound = classbreakvalues[i]
                brk.label = classbreaklabels[i]
                i+=1

                layer.symbology = sym

#                     aprx.save()
    c+=1

 

0 Kudos