Select to view content in your preferred language

Get list of layer’s symbology classes and symbol labels using ArcPy?

2858
5
Jump to solution
12-06-2022 08:08 PM
Bud
by
Honored Contributor

I'm working with a FGDB FC that has data, of sorts, stored in the symbology. 
What I mean is: there is UNIT information in the symbology as labels, yet that UNIT information doesn't exist in a field in the attribute table of the FC anywhere.

Bud_0-1670201070234.png

Using ArcPy, is there a way to print a list of the layer’s symbology class values and symbol labels? I have 20+ layers, all with different symbology, so it would be ideal if I could do it programmatically.

If I could get a list, then I could manually:

  • Copy/paste that list into a lookup table, either in Excel or right in the attribute table.
  • Join from the layer to the lookup table via the common COLOR field.
  • Use the field calculator to update a new UNIT field in the layer.
  • Use the layer’s new UNIT field for analysis as required.

I’m new to ArcPy. I’ve tried to modify a couple of sample scripts online. But I don’t really know what I’m doing yet. Any tips would be appreciated.

ArcGIS Pro 3.0.3.

 

Related: Export symbology classes to a table

Tags (2)
0 Kudos
1 Solution

Accepted Solutions
JohannesLindner
MVP Frequent Contributor

You can get the symbology of a layer. Form there, you'll have to follow the rabbit hole to the single symbology items.

This script will loop through a list of layers in the active map, analyze their symbology and add a new field to each layer with the symbology's label value:

layer_names = ["TestPolygons"]
aprx = arcpy.mp.ArcGISProject("current")

for name in layer_names:
    # get the layer
    layer = aprx.activeMap.listLayers(name)[0]
    # get the symbology fields and items
    renderer = layer.symbology.renderer
    fields = renderer.fields
    items = renderer.groups[0].items
    # create a dict {values: label}
    item_dict = {tuple(i.values[0]): i.label for i in items}
    # add a new field
    arcpy.management.AddField(layer, "Unit", "TEXT")
    # insert the label values
    with arcpy.da.UpdateCursor(layer, ["Unit"] + fields) as cursor:
        for row in cursor:
            key = tuple([str(x) for x in row[1:]])  # item.values stores values as string
            try:
                row[0] = item_dict[key]
                cursor.updateRow(row)
            except KeyError:  # no symbology found
                pass

 

JohannesLindner_0-1670407418636.png

 


Have a great day!
Johannes

View solution in original post

5 Replies
JohannesLindner
MVP Frequent Contributor

You can get the symbology of a layer. Form there, you'll have to follow the rabbit hole to the single symbology items.

This script will loop through a list of layers in the active map, analyze their symbology and add a new field to each layer with the symbology's label value:

layer_names = ["TestPolygons"]
aprx = arcpy.mp.ArcGISProject("current")

for name in layer_names:
    # get the layer
    layer = aprx.activeMap.listLayers(name)[0]
    # get the symbology fields and items
    renderer = layer.symbology.renderer
    fields = renderer.fields
    items = renderer.groups[0].items
    # create a dict {values: label}
    item_dict = {tuple(i.values[0]): i.label for i in items}
    # add a new field
    arcpy.management.AddField(layer, "Unit", "TEXT")
    # insert the label values
    with arcpy.da.UpdateCursor(layer, ["Unit"] + fields) as cursor:
        for row in cursor:
            key = tuple([str(x) for x in row[1:]])  # item.values stores values as string
            try:
                row[0] = item_dict[key]
                cursor.updateRow(row)
            except KeyError:  # no symbology found
                pass

 

JohannesLindner_0-1670407418636.png

 


Have a great day!
Johannes
VincentLaunstorfer
Regular Contributor

Hi Johannes,

I found your python script really interesting as there is no easy solution to export symbology labels to table or field. However, I still get an error when trying to run your script.

I simply changed the first line in order to drag & drop layers from the current/active projects, using:

layer_names = sys.argv[1]

And I get the following error:

layer = aprx.activeMap.listLayers(name)[0]
IndexError: list index out of range

It should be obvious to fix but I do not have much experience with the arcpy mp module and I am stuck.

Any help would be appreciated. Thanks

layer_names = sys.argv[1]
aprx = arcpy.mp.ArcGISProject("current")

for name in layer_names:
    # get the layer
    layer = aprx.activeMap.listLayers(name)[0]
    # get the symbology fields and items
    renderer = layer.symbology.renderer
    fields = renderer.fields
    items = renderer.groups[0].items
    # create a dict {values: label}
    item_dict = {tuple(i.values[0]): i.label for i in items}
    # add a new field
    arcpy.management.AddField(layer, "Unit", "TEXT")
    # insert the label values
    with arcpy.da.UpdateCursor(layer, ["Unit"] + fields) as cursor:
        for row in cursor:
            key = tuple([str(x) for x in row[1:]])  # item.values stores values as string
            try:
                row[0] = item_dict[key]
                cursor.updateRow(row)
            except KeyError:  # no symbology found
                pass

 

0 Kudos
JohannesLindner
MVP Frequent Contributor

layer_names has to be a list (or other collection type).

My guess is that sys.argv[1] is a string, which the script iterates through, taking each letter as layer name. listLayers("a") returns an empty list, and then it correctly raises the IndexError when you try to access the first element of that empty list.


Have a great day!
Johannes
0 Kudos
VincentLaunstorfer
Regular Contributor

You think setting up a dialog box properties for the Python script with a parameter (sys.arg[1]) defined as Layer multiple value, is read as a String? Should I read this parameter in a loop and assign the values to the List?

I though it may come from the script expecting a layer name only, and not the entire layer name with path... I will try to 'hard-code' the layer name making a list with a single entry...

0 Kudos
JohannesLindner
MVP Frequent Contributor

sys.argv is used to call scripts from command line, right? I have absolutely no experience with that. The script above is supposed to be executed in the ArcGIS Pro Python window.


Have a great day!
Johannes
0 Kudos