Select to view content in your preferred language

Get Unique Values from a Field (Maybe Statistics Too?)

2087
4
12-13-2023 09:17 PM
Status: Open
Labels (1)
DaveFullerton
Frequent Contributor

Get Unique Values from a Field (Maybe Statistics Too?)

Getting unique values from a field in code can be done using the snippet provided by @RichRuh :

https://community.esri.com/t5/arcgis-pro-sdk-questions/getting-statistics-on-a-field/td-p/846351

But there are limitations. It took a while to find them, and it is very possible I didn’t find them all.

For our use case, the goal is to allow the user to use any layer of type FeatureLayer in the map’s contents as part of their work process.  Streamlining the process through code involves asking them to select from 3 combo boxes:  map layer name, then field name, and finally field value.

The code snippet from the post above throws exceptions when used with XY Event Layers, and as far as I can see, most feature layers that have a joined table (click link above for more information).

I think it might not be too hard to get something into the API that provides unique values since it is already done in the Pro GUI, for example, in the “Select By Attributes” tool.  But I thought I would mention Statistics as well since it is very much related and worth considering at the same time.  If anyone wants to see that in the API too, it would make sense to leave a comment with details about use cases for that.

4 Comments
MattHowe

Love the idea, especially if it was inbuilt as a normal tool in Pro. You can run a few lines of Python to get the unique values and then some follow up stats that might be more workable. The Pandas library has a nice summary statistics method.

 

import arcpy
import pandas as pd
my_layer = r"C:\\test.shp"
stats_field = "DEPTHS_M"
unique_value_list = [row[0] for row in arcpy.da.SearchCursor(my_layer, [stats_field]]
unique_value_set = set(unique_value_list)
final_list = list(unique_value_set)
stats = pd.Series(final_list)
stats.describe()
# Should give summary stats like count, mean, standard deviation, min, max, and a few percentiles.

 

Bud
by

This isn't what you're asking for, but it still might be of interest:

We could get a list of unique values for a given field using a SQL subquery. A subquery would work in mobile and enterprise geodatabases, but I couldn't get it to work in a file geodatabase.


Sample data (the TYPE field has duplicates):

Bud_0-1702547846664.png

 

Option 1 — Use Select By Attributes: (or a definition query)

Bud_1-1702548080707.png

 objectid in (
    select
        min(objectid) as objectid
    from
        a_test_fc
    group by
        type)


Option 2 — Create a database view: (or a query layer in an enterprise geodatabase)

Bud_3-1702548275387.png

Bud_5-1702548327111.png

select
    objectid,
    type
from
    a_test_fc
where
    objectid in (
        select
            min(objectid) as objectid
        from
            a_test_fc
        group by
            type)
order by
    type

Edit: In hindsight, I didn't need to include the OBJECTID as a field in the view. I could have just used the TYPE field as the unique ID.

 

Those techniques give us a "list of unique values" in the attribute table. We're querying for the first arbitrary row in each group.

Bud
by
MichaelHanson1

Just throwing my solution in the mix in case it's helpful to someone. I created a new tool in ArcGIS Pro with two parameters to input the name of the Feature Class (must be present in the current map) and another for the Field.

I used a dictionary to also return the count of features with each value.

# Get parameters from the user
fc = arcpy.GetParameterAsText(0)  # Feature class or layer name from the map
field = arcpy.GetParameterAsText(1)  # Field name to get unique values from

# Reference the layer in the current map
layer = arcpy.mp.ArcGISProject("CURRENT").activeMap.listLayers(fc)[0]

# Create a dictionary to store the unique values and their counts
value_counts = {}

# Use a SearchCursor to iterate through the field and count occurrences
with arcpy.da.SearchCursor(layer, [field]) as cursor:
    for row in cursor:
        value = row[0]
        if value in value_counts:
            value_counts[value] += 1
        else:
            value_counts[value] = 1

# Output the unique values and their counts using arcpy.AddMessage
arcpy.AddMessage(f"Unique values and their counts from the field '{field}':")

# Format the output as a table with headers
arcpy.AddMessage(f"{'Value':<20} {'Count':<10}")
arcpy.AddMessage("-" * 30)

# Display each unique value with its count
for value, count in value_counts.items():
    arcpy.AddMessage(f"{str(value):<20} {str(count):<10}")

 

MichaelHanson1_0-1728662643016.png

 

When I run the tool it looks like this:

MichaelHanson1_1-1728662696288.png

 

And the output looks like this in the Details window after running:

 

MichaelHanson1_2-1728662734111.png