Select to view content in your preferred language

Question about Exposing the Unique Renderer Symbology Count Values

890
5
10-17-2022 10:26 AM
anonymous_geographer
Frequent Contributor

Hello everyone,

Does anyone know if Esri has exposed the Count values within Python's ArcPy for the unique value renderer items? The current documentation indicates that the Item's description, label, symbol, and values are exposed via Python. However, ArcGIS Pro allows you to also display the number of occurrences per item by toggling the Count field (i.e. Show Count) within the Symbology pane:

anonymous_geographer_0-1666026853534.png


Unfortunately, I am unable to find this option within Python thus far.

For our workflow, we do not "refresh" our unique value symbology each time a change is made. Pre-existing symbology needs to remain static. Because of that, we opt to add missing values (with .listMissingValues()). Afterwards, we manually go into ArcGIS Pro and check/remove any out-dated unique values that show a Count of 0:

anonymous_geographer_1-1666027304566.png


I'd like to automate this process where the script removes any unique values with a Count of 0, but that doesn't appear to be possible based on the documentation I've found thus far. I may be looking in the wrong place though.

Does anybody have any insight into this, or if it's even possible via Python? Thanks!

0 Kudos
5 Replies
by Anonymous User
Not applicable

You 'could' maybe do a length on the itm.values to get a count.

 

len(itm.values)

 

Or you could maybe go about it a different way and run your own summary/ cnt type cursor on the dataset, using the same field that the renderer is using into a dictionary.  Then iterate over the sym,renderer.groups and if the value is not in the dictionary you created earlier, remove it.

!!!!!!!!!

EDIT:  The len() method doesn't work.. The list of values in the items is the value from any field that is used for the renderer so if you only have one field, there will be one value.  bummer!

At this point, I'd use a cursor to determine counts and then recursively remove the items from the renderer that do have a match.

0 Kudos
anonymous_geographer
Frequent Contributor

Hey Jeff,

I initially tried that, but itm.values doesn't work the way you think it does. An item's values refer to the grouped name classifications only. For example, if I have rendered a unique value with "Neighborhood A", the item value will be "Neighborhood A" with an itm.values length of 1. Hypothetically, if I have combined/grouped several classification names into one unique value (such as "Neighborhood A", "Neighborhood B", and "Neighborhood C"), then the itm.values length will be 3.

Sadly, the itm.values information is used in a completely seperate way than counting the total number of features per unique value rendered.

I might be able to pull something off with your second idea, but this might be too sluggish with the number of features we have to review each time. Thanks for the idea there, I may build something to test with and see how it goes. I may also end up submitting the renderer's feature count functionality as an enhancement to Esri. I'm not sure why they'd expose that conveniently within Pro, but not within Python.

0 Kudos
AlfredBaldenweck
MVP Regular Contributor

Shot in the dark, but is there like an item.values.values property?

0 Kudos
anonymous_geographer
Frequent Contributor

Haha, I was hopeful with that idea too originally! I can confirm that item.values.values (and item.values.count, for that matter) does not work.
"AttributeError: 'list' object has no attribute 'values'"

0 Kudos
by Anonymous User
Not applicable

I was thinking it would have a list of the values that fit that value, but it just drills down to just the single value of the values:

uniqueRend.png

 

Here is an example of the recursive remove:

 

p = arcpy.mp.ArcGISProject(r'C:\...\Analysis.aprx')
m = p.listMaps('Map')[0]
l = m.listLayers('wait_times*')[0]
sym = l.symbology

dct = {}

with arcpy.da.SearchCursor(l, ['uniqueRendField']) as sCur:
    for row in sCur:
        if dct.get(str(row[0])): #<- cast to string since the values in the renderer items are strings
            dct[str(row[0])] = dct[str(row[0])] + 1
        else:
            dct[str(row[0])] = 1

sym.updateRenderer('UniqueValueRenderer')
sym.renderer.fields = ['uniqueRendField']
for grp in sym.renderer.groups:
    for itm in grp.items:
        if not dct.get(itm.values[0][0]):
            sym.renderer.removeValues({'uniqueRendField' : [itm.values[0][0]]})
            l.symbology = sym

 

 

0 Kudos